Big Endian Support Removal.

This commit implements #125759.

It removes:
* Blender does not build on big endian systems anymore.
* Support for opening blendfiles written from a big endian system is
  removed.

It keeps:
* Support to generate thumbnails from big endian blendfiles.
* BE support in `extern` or `intern` libraries, including Cycles.
* Support to open big endian versions of third party file formats:
  - PLY files.
  - Some image files (cineon, ...).

Pull Request: https://projects.blender.org/blender/blender/pulls/140138
This commit is contained in:
Bastien Montagne 2025-06-12 10:37:47 +02:00 committed by Bastien Montagne
parent 05d0391ed6
commit bc80ef136e
44 changed files with 438 additions and 651 deletions

View File

@ -1631,32 +1631,16 @@ if(FIRST_RUN)
endif() endif()
endif() endif()
# set the endian define # Test endianness and set the endian define.
if(MSVC) include(TestBigEndian)
# For some reason this fails on MSVC. test_big_endian(_SYSTEM_BIG_ENDIAN)
add_definitions(-D__LITTLE_ENDIAN__) if(_SYSTEM_BIG_ENDIAN)
message(FATAL_ERROR "Blender does not support building on Big Endian systems" )
# OSX-Note: as we do cross-compiling with specific set architecture,
# endianness-detection and auto-setting is counterproductive
# so we just set endianness according CMAKE_OSX_ARCHITECTURES
elseif(CMAKE_OSX_ARCHITECTURES MATCHES i386 OR
CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR
CMAKE_OSX_ARCHITECTURES MATCHES arm64)
add_definitions(-D__LITTLE_ENDIAN__)
elseif(CMAKE_OSX_ARCHITECTURES MATCHES ppc OR CMAKE_OSX_ARCHITECTURES MATCHES ppc64)
add_definitions(-D__BIG_ENDIAN__)
else() else()
include(TestBigEndian) add_definitions(-D__LITTLE_ENDIAN__)
test_big_endian(_SYSTEM_BIG_ENDIAN)
if(_SYSTEM_BIG_ENDIAN)
add_definitions(-D__BIG_ENDIAN__)
else()
add_definitions(-D__LITTLE_ENDIAN__)
endif()
unset(_SYSTEM_BIG_ENDIAN)
endif() endif()
unset(_SYSTEM_BIG_ENDIAN)
if(WITH_IMAGE_OPENJPEG) if(WITH_IMAGE_OPENJPEG)
# Special handling of Windows platform where openjpeg is always static. # Special handling of Windows platform where openjpeg is always static.
if(WIN32) if(WIN32)

View File

@ -174,11 +174,8 @@ static const char *check_memlist(const MemHead *memh);
/* locally used defines */ /* locally used defines */
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
# define MAKE_ID(a, b, c, d) (int(a) << 24 | int(b) << 16 | (c) << 8 | (d)) #define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
#else
# define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
#endif
#define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O') #define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
#define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L') #define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')

View File

@ -14,13 +14,9 @@
/* clang-format off */ /* clang-format off */
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
# define RGBA(c) {((c) >> 24) & 0xff, ((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff} #define RGBA(c) {((c) >> 24) & 0xff, ((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff}
# define RGB(c) {((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff} #define RGB(c) {((c) >> 16) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff}
#else
# define RGBA(c) {(c) & 0xff, ((c) >> 8) & 0xff, ((c) >> 16) & 0xff, ((c) >> 24) & 0xff}
# define RGB(c) {(c) & 0xff, ((c) >> 8) & 0xff, ((c) >> 16) & 0xff}
#endif
const bTheme U_theme_default = { const bTheme U_theme_default = {
.name = "Default", .name = "Default",

View File

@ -45,10 +45,5 @@ std::optional<blender::Vector<uint8_t>> blendthumb_create_png_data_from_thumb(
eThumbStatus blendthumb_create_thumb_from_file(FileReader *rawfile, Thumbnail *thumb); eThumbStatus blendthumb_create_thumb_from_file(FileReader *rawfile, Thumbnail *thumb);
/* INTEGER CODES */ /* INTEGER CODES */
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* Big Endian */ #define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
#else
/* Little Endian */
# define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
#endif

View File

@ -14,7 +14,6 @@
#include "BLI_alloca.h" #include "BLI_alloca.h"
#include "BLI_endian_defines.h" #include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_filereader.h" #include "BLI_filereader.h"
#include "BLI_string.h" #include "BLI_string.h"
@ -24,6 +23,8 @@
#include "blendthumb.hh" #include "blendthumb.hh"
BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
static void thumb_data_vertical_flip(Thumbnail *thumb) static void thumb_data_vertical_flip(Thumbnail *thumb)
{ {
uint32_t *rect = (uint32_t *)thumb->data.data(); uint32_t *rect = (uint32_t *)thumb->data.data();
@ -43,13 +44,12 @@ static void thumb_data_vertical_flip(Thumbnail *thumb)
free(line); free(line);
} }
static int32_t bytes_to_native_i32(const uint8_t bytes[4], bool endian_switch) static int32_t bytes_to_native_i32(const uint8_t bytes[4])
{ {
int32_t data; int32_t data;
memcpy(&data, bytes, 4); memcpy(&data, bytes, 4);
if (endian_switch) { /* NOTE: this is endianness-sensitive. */
BLI_endian_switch_int32(&data); /* PNG is always little-endian, and would require switching on a big-endian system. */
}
return data; return data;
} }
@ -84,12 +84,11 @@ static eThumbStatus blendthumb_extract_from_file_impl(FileReader *file,
Thumbnail *thumb, Thumbnail *thumb,
const BlenderHeader &header) const BlenderHeader &header)
{ {
const bool endian_switch = header.endian != ENDIAN_ORDER; BLI_assert(header.endian == L_ENDIAN);
/* Iterate over file blocks until we find the thumbnail or run out of data. */ /* Iterate over file blocks until we find the thumbnail or run out of data. */
while (true) { while (true) {
/* Read next BHead. */ /* Read next BHead. */
const std::optional<BHead> bhead = BLO_readfile_read_bhead( const std::optional<BHead> bhead = BLO_readfile_read_bhead(file, header.bhead_type());
file, header.bhead_type(), endian_switch);
if (!bhead.has_value()) { if (!bhead.has_value()) {
/* File has ended. */ /* File has ended. */
return BT_INVALID_THUMB; return BT_INVALID_THUMB;
@ -104,8 +103,8 @@ static eThumbStatus blendthumb_extract_from_file_impl(FileReader *file,
if (!file_read(file, shape, sizeof(shape))) { if (!file_read(file, shape, sizeof(shape))) {
return BT_INVALID_THUMB; return BT_INVALID_THUMB;
} }
thumb->width = bytes_to_native_i32(&shape[0], endian_switch); thumb->width = bytes_to_native_i32(&shape[0]);
thumb->height = bytes_to_native_i32(&shape[4], endian_switch); thumb->height = bytes_to_native_i32(&shape[4]);
/* Verify that image dimensions and data size make sense. */ /* Verify that image dimensions and data size make sense. */
size_t data_size = bhead->len - sizeof(shape); size_t data_size = bhead->len - sizeof(shape);
@ -190,6 +189,13 @@ eThumbStatus blendthumb_create_thumb_from_file(FileReader *rawfile, Thumbnail *t
return BT_EARLY_VERSION; return BT_EARLY_VERSION;
} }
/* Check if the file was written from a big-endian build. */
if (header.endian != L_ENDIAN) {
file->close(file);
return BT_INVALID_FILE;
}
BLI_assert(header.endian == ENDIAN_ORDER);
/* Read the thumbnail. */ /* Read the thumbnail. */
eThumbStatus err = blendthumb_extract_from_file_impl(file, thumb, header); eThumbStatus err = blendthumb_extract_from_file_impl(file, thumb, header);
file->close(file); file->close(file);

View File

@ -21,9 +21,9 @@
static void png_extend_native_int32(blender::Vector<uint8_t> &output, int32_t data) static void png_extend_native_int32(blender::Vector<uint8_t> &output, int32_t data)
{ {
if (ENDIAN_ORDER == L_ENDIAN) { /* NOTE: this is endianness-sensitive. */
BLI_endian_switch_int32(&data); /* PNG is big-endian, its values need to be switched on little-endian systems. */
} BLI_endian_switch_int32(&data);
output.extend_unchecked(blender::Span((uint8_t *)&data, 4)); output.extend_unchecked(blender::Span((uint8_t *)&data, 4));
} }

View File

@ -24,7 +24,6 @@
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "BLI_endian_switch.h"
#include "BLI_ghash.h" #include "BLI_ghash.h"
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_math_color.h" #include "BLI_math_color.h"
@ -671,12 +670,11 @@ static void read_slots(BlendDataReader *reader, animrig::Action &action)
for (int i = 0; i < action.slot_array_num; i++) { for (int i = 0; i < action.slot_array_num; i++) {
BLO_read_struct(reader, ActionSlot, &action.slot_array[i]); BLO_read_struct(reader, ActionSlot, &action.slot_array[i]);
/* Undo generic endian switching, as the ID type values are not numerically the same between /* NOTE: this is endianness-sensitive. */
* little and big endian machines. Due to the way they are defined, they are always in the same /* In case of required endian switching, this code would have to undo the generic endian
* byte order, regardless of hardware/platform endianness. */ * switching, as the ID type values are not numerically the same between little and big endian
if (BLO_read_requires_endian_switch(reader)) { * machines. Due to the way they are defined, they are always in the same byte order,
BLI_endian_switch_int16(&action.slot_array[i]->idtype); * regardless of hardware/platform endianness. */
}
action.slot_array[i]->wrap().blend_read_post(); action.slot_array[i]->wrap().blend_read_post();
} }
@ -686,12 +684,10 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id)
{ {
animrig::Action &action = reinterpret_cast<bAction *>(id)->wrap(); animrig::Action &action = reinterpret_cast<bAction *>(id)->wrap();
/* Undo generic endian switching (careful, only the two least significant bytes of the int32 must /* NOTE: this is endianness-sensitive. */
* be swapped back here, since this value is actually an int16). */ /* In case of required endianness switching, this code would need to undo the generic endian
if (BLO_read_requires_endian_switch(reader)) { * switching (careful, only the two least significant bytes of the int32 must be swapped back
bAction *act = reinterpret_cast<bAction *>(id); * here, since this value is actually an int16). */
BLI_endian_switch_int16(reinterpret_cast<short *>(&act->idroot));
}
read_strip_keyframe_data_array(reader, action); read_strip_keyframe_data_array(reader, action);
read_layers(reader, action); read_layers(reader, action);

View File

@ -15,7 +15,6 @@
#include "BKE_volume.hh" #include "BKE_volume.hh"
#include "BLI_endian_defines.h" #include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_math_matrix_types.hh" #include "BLI_math_matrix_types.hh"
#include "BLI_path_utils.hh" #include "BLI_path_utils.hh"
@ -289,11 +288,8 @@ std::optional<ImplicitSharingInfoAndData> BlobReadSharing::read_shared(
static StringRefNull get_endian_io_name(const int endian) static StringRefNull get_endian_io_name(const int endian)
{ {
if (endian == L_ENDIAN) { BLI_assert(endian == L_ENDIAN);
return "little"; return "little";
}
BLI_assert(endian == B_ENDIAN);
return "big";
} }
static StringRefNull get_domain_io_name(const AttrDomain domain) static StringRefNull get_domain_io_name(const AttrDomain domain)
@ -329,7 +325,7 @@ static std::optional<eCustomDataType> get_data_type_from_io_name(const StringRef
} }
/** /**
* Write the data and remember which endianness the data had. * Write the data, always in little endian.
*/ */
static std::shared_ptr<DictionaryValue> write_blob_raw_data_with_endian( static std::shared_ptr<DictionaryValue> write_blob_raw_data_with_endian(
BlobWriter &blob_writer, BlobWriter &blob_writer,
@ -338,14 +334,14 @@ static std::shared_ptr<DictionaryValue> write_blob_raw_data_with_endian(
const int64_t size_in_bytes) const int64_t size_in_bytes)
{ {
auto io_data = blob_sharing.write_deduplicated(blob_writer, data, size_in_bytes); auto io_data = blob_sharing.write_deduplicated(blob_writer, data, size_in_bytes);
if (ENDIAN_ORDER == B_ENDIAN) { BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
io_data->append_str("endian", get_endian_io_name(ENDIAN_ORDER));
}
return io_data; return io_data;
} }
/** /**
* Read data of an into an array and optionally perform an endian switch if necessary. * Read data of an into an array.
*
* \returns True if sucessful, false if reading fails, or endian switch would be needed.
*/ */
[[nodiscard]] static bool read_blob_raw_data_with_endian(const BlobReader &blob_reader, [[nodiscard]] static bool read_blob_raw_data_with_endian(const BlobReader &blob_reader,
const DictionaryValue &io_data, const DictionaryValue &io_data,
@ -367,21 +363,9 @@ static std::shared_ptr<DictionaryValue> write_blob_raw_data_with_endian(
const StringRefNull current_endian = get_endian_io_name(ENDIAN_ORDER); const StringRefNull current_endian = get_endian_io_name(ENDIAN_ORDER);
const bool need_endian_switch = stored_endian != current_endian; const bool need_endian_switch = stored_endian != current_endian;
if (need_endian_switch) { if (need_endian_switch) {
switch (element_size) { /* NOTE: this is endianness-sensitive. */
case 1: /* Blender only builds on little endian systems, and reads little endian data here. */
break; return false;
case 2:
BLI_endian_switch_uint16_array(static_cast<uint16_t *>(r_data), elements_num);
break;
case 4:
BLI_endian_switch_uint32_array(static_cast<uint32_t *>(r_data), elements_num);
break;
case 8:
BLI_endian_switch_uint64_array(static_cast<uint64_t *>(r_data), elements_num);
break;
default:
return false;
}
} }
return true; return true;
} }

View File

@ -13,7 +13,6 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_endian_defines.h" #include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
@ -78,7 +77,6 @@ struct CDataFile {
FILE *readf; FILE *readf;
FILE *writef; FILE *writef;
int switchendian;
size_t dataoffset; size_t dataoffset;
}; };
@ -86,11 +84,8 @@ struct CDataFile {
static int cdf_endian() static int cdf_endian()
{ {
if (ENDIAN_ORDER == L_ENDIAN) { BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
return CDF_ENDIAN_LITTLE; return CDF_ENDIAN_LITTLE;
}
return CDF_ENDIAN_BIG;
} }
CDataFile *cdf_create(int type) CDataFile *cdf_create(int type)
@ -138,15 +133,14 @@ static bool cdf_read_header(CDataFile *cdf)
if (header->version > CDF_VERSION) { if (header->version > CDF_VERSION) {
return false; return false;
} }
if (header->endian != cdf_endian()) {
return false;
}
cdf->switchendian = header->endian != cdf_endian();
header->endian = cdf_endian(); header->endian = cdf_endian();
if (cdf->switchendian) { /* NOTE: this is endianness-sensitive.
BLI_endian_switch_int32(&header->type); * Some non-char `header` data would need to be switched. */
BLI_endian_switch_int32(&header->totlayer);
BLI_endian_switch_int32(&header->structbytes);
}
if (!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) { if (!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) {
return false; return false;
@ -165,12 +159,8 @@ static bool cdf_read_header(CDataFile *cdf)
return false; return false;
} }
if (cdf->switchendian) { /* NOTE: this is endianness-sensitive.
BLI_endian_switch_int32(&image->width); * Some non-char `image` data would need to be switched. */
BLI_endian_switch_int32(&image->height);
BLI_endian_switch_int32(&image->tile_size);
BLI_endian_switch_int32(&image->structbytes);
}
offset += image->structbytes; offset += image->structbytes;
image->structbytes = sizeof(CDataFileImageHeader); image->structbytes = sizeof(CDataFileImageHeader);
@ -181,9 +171,8 @@ static bool cdf_read_header(CDataFile *cdf)
return false; return false;
} }
if (cdf->switchendian) { /* NOTE: this is endianness-sensitive.
BLI_endian_switch_int32(&mesh->structbytes); * Some non-char `mesh` data would need to be switched. */
}
offset += mesh->structbytes; offset += mesh->structbytes;
mesh->structbytes = sizeof(CDataFileMeshHeader); mesh->structbytes = sizeof(CDataFileMeshHeader);
@ -207,12 +196,8 @@ static bool cdf_read_header(CDataFile *cdf)
return false; return false;
} }
if (cdf->switchendian) { /* NOTE: this is endianness-sensitive.
BLI_endian_switch_int32(&layer->type); * Some non-char `layer` data would need to be switched. */
BLI_endian_switch_int32(&layer->datatype);
BLI_endian_switch_uint64(&layer->datasize);
BLI_endian_switch_int32(&layer->structbytes);
}
if (layer->datatype != CDF_DATA_FLOAT) { if (layer->datatype != CDF_DATA_FLOAT) {
return false; return false;
@ -319,10 +304,8 @@ bool cdf_read_data(CDataFile *cdf, uint size, void *data)
return false; return false;
} }
/* switch endian if necessary */ /* NOTE: this is endianness-sensitive.
if (cdf->switchendian) { * `data` would need to be switched. */
BLI_endian_switch_float_array(static_cast<float *>(data), size / sizeof(float));
}
return true; return true;
} }

View File

@ -15,7 +15,6 @@
#include <fmt/format.h> #include <fmt/format.h>
#include "BLI_endian_switch.h"
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_math_base.h" #include "BLI_math_base.h"
#include "BLI_set.hh" #include "BLI_set.hh"
@ -1621,18 +1620,12 @@ static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader)
IDP_DirectLinkIDPArray(prop, reader); IDP_DirectLinkIDPArray(prop, reader);
break; break;
case IDP_DOUBLE: case IDP_DOUBLE:
/* Workaround for doubles. /* NOTE: this is endianness-sensitive. */
* They are stored in the same field as `int val, val2` in the #IDPropertyData struct, /* Doubles are stored in the same field as `int val, val2` in the #IDPropertyData struct.
* they have to deal with endianness specifically.
* *
* In theory, val and val2 would've already been swapped * In case of endianness switching, `val` and `val2` would have already been switched by the
* if switch_endian is true, so we have to first un-swap * generic reading code, so they would need to be first un-switched individually, and then
* them then re-swap them as a single 64-bit entity. */ * re-switched as a single 64-bit entity. */
if (BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int32(&prop->data.val);
BLI_endian_switch_int32(&prop->data.val2);
BLI_endian_switch_int64((int64_t *)&prop->data.val);
}
break; break;
case IDP_INT: case IDP_INT:
case IDP_FLOAT: case IDP_FLOAT:

View File

@ -37,7 +37,6 @@
#include "DNA_world_types.h" #include "DNA_world_types.h"
#include "BLI_dynstr.h" #include "BLI_dynstr.h"
#include "BLI_endian_switch.h"
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_string_utils.hh" #include "BLI_string_utils.hh"
@ -126,38 +125,15 @@ static void ipo_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_struct_list(reader, IpoCurve, &(ipo->curve)); BLO_read_struct_list(reader, IpoCurve, &(ipo->curve));
/* NOTE: this is endianness-sensitive.
* Not clear why, but endianness switching was undone here for some data?
* That 'undo switching' code appeared to be heavily broken in 4.x code actually, performing
* switch on `ipo` data as part of the loop on `icu`'s, among other obvious mistakes. */
LISTBASE_FOREACH (IpoCurve *, icu, &ipo->curve) { LISTBASE_FOREACH (IpoCurve *, icu, &ipo->curve) {
BLO_read_struct_array(reader, BezTriple, icu->totvert, &icu->bezt); BLO_read_struct_array(reader, BezTriple, icu->totvert, &icu->bezt);
BLO_read_struct_array(reader, BPoint, icu->totvert, &icu->bp); BLO_read_struct_array(reader, BPoint, icu->totvert, &icu->bp);
BLO_read_struct(reader, IpoDriver, &icu->driver); BLO_read_struct(reader, IpoDriver, &icu->driver);
/* Undo generic endian switching. */
if (BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int16(&icu->blocktype);
if (icu->driver != nullptr) {
/* Undo generic endian switching. */
if (BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int16(&icu->blocktype);
if (icu->driver != nullptr) {
BLI_endian_switch_int16(&icu->driver->blocktype);
}
}
}
/* Undo generic endian switching. */
if (BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int16(&ipo->blocktype);
if (icu->driver != nullptr) {
BLI_endian_switch_int16(&icu->driver->blocktype);
}
}
}
}
/* Undo generic endian switching. */
if (BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int16(&ipo->blocktype);
} }
} }

View File

@ -14,7 +14,6 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_math_matrix.h" #include "BLI_math_matrix.h"
#include "BLI_math_vector.h" #include "BLI_math_vector.h"
@ -151,33 +150,6 @@ static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_add
#define IPO_BEZTRIPLE 100 #define IPO_BEZTRIPLE 100
#define IPO_BPOINT 101 #define IPO_BPOINT 101
static void switch_endian_keyblock(Key *key, KeyBlock *kb)
{
int elemsize = key->elemsize;
char *data = static_cast<char *>(kb->data);
for (int a = 0; a < kb->totelem; a++) {
const char *cp = key->elemstr;
char *poin = data;
while (cp[0]) { /* cp[0] == amount */
switch (cp[1]) { /* cp[1] = type */
case IPO_FLOAT:
case IPO_BPOINT:
case IPO_BEZTRIPLE: {
int b = cp[0];
BLI_endian_switch_float_array((float *)poin, b);
poin += sizeof(float) * b;
break;
}
}
cp += 2;
}
data += elemsize;
}
}
static void shapekey_blend_read_data(BlendDataReader *reader, ID *id) static void shapekey_blend_read_data(BlendDataReader *reader, ID *id)
{ {
Key *key = (Key *)id; Key *key = (Key *)id;
@ -188,9 +160,9 @@ static void shapekey_blend_read_data(BlendDataReader *reader, ID *id)
LISTBASE_FOREACH (KeyBlock *, kb, &key->block) { LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
BLO_read_data_address(reader, &kb->data); BLO_read_data_address(reader, &kb->data);
if (BLO_read_requires_endian_switch(reader)) { /* NOTE: this is endianness-sensitive. */
switch_endian_keyblock(key, kb); /* Keyblock data would need specific endian switching depending of the exact type of data it
} * contain. */
} }
} }

View File

@ -21,7 +21,6 @@
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "BLI_bounds.hh" #include "BLI_bounds.hh"
#include "BLI_endian_switch.h"
#include "BLI_hash.h" #include "BLI_hash.h"
#include "BLI_implicit_sharing.hh" #include "BLI_implicit_sharing.hh"
#include "BLI_index_range.hh" #include "BLI_index_range.hh"
@ -430,12 +429,9 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
mesh->totselect = 0; mesh->totselect = 0;
} }
if (BLO_read_requires_endian_switch(reader) && mesh->tface) { /* NOTE: this is endianness-sensitive. */
TFace *tf = mesh->tface; /* Each legacy TFace would need to undo the automatic DNA switch of its array of four uint32_t
for (int i = 0; i < mesh->totface_legacy; i++, tf++) { * RGBA colors. */
BLI_endian_switch_uint32_array(tf->col, 4);
}
}
} }
IDTypeInfo IDType_ID_ME = { IDTypeInfo IDType_ID_ME = {

View File

@ -987,6 +987,7 @@ void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p, Strin
if (pf == nullptr) { if (pf == nullptr) {
return; return;
} }
/* NOTE: this is endianness-sensitive. */
/* NOTE: there is no way to handle endianness switch here. */ /* NOTE: there is no way to handle endianness switch here. */
pf->sharing_info = BLO_read_shared(reader, &pf->data, [&]() { pf->sharing_info = BLO_read_shared(reader, &pf->data, [&]() {
BLO_read_data_address(reader, &pf->data); BLO_read_data_address(reader, &pf->data);

View File

@ -46,19 +46,11 @@
#endif #endif
/* NOTE: copied from BLO_core_bhead.hh, don't use here because we're in BLI. */ /* NOTE: copied from BLO_core_bhead.hh, don't use here because we're in BLI. */
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* Big Endian */ #define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) #define MAKE_ID_8(a, b, c, d, e, f, g, h) \
# define MAKE_ID_8(a, b, c, d, e, f, g, h) \ (int64_t(h) << 56 | int64_t(g) << 48 | int64_t(f) << 40 | int64_t(e) << 32 | int64_t(d) << 24 | \
((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \ int64_t(c) << 16 | int64_t(b) << 8 | (a))
(int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h))
#else
/* Little Endian */
# define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
(int64_t(h) << 56 | int64_t(g) << 48 | int64_t(f) << 40 | int64_t(e) << 32 | \
int64_t(d) << 24 | int64_t(c) << 16 | int64_t(b) << 8 | (a))
#endif
/** /**
* Important that this value is an is _not_ aligned with `sizeof(void *)`. * Important that this value is an is _not_ aligned with `sizeof(void *)`.

View File

@ -13,10 +13,6 @@
#include "BLI_fileops.hh" #include "BLI_fileops.hh"
#include "BLI_filereader.h" #include "BLI_filereader.h"
#ifdef __BIG_ENDIAN__
# include "BLI_endian_switch.h"
#endif
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
struct ZstdReader { struct ZstdReader {
@ -43,9 +39,8 @@ static bool zstd_read_u32(FileReader *base, uint32_t *val)
if (base->read(base, val, sizeof(uint32_t)) != sizeof(uint32_t)) { if (base->read(base, val, sizeof(uint32_t)) != sizeof(uint32_t)) {
return false; return false;
} }
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive.
BLI_endian_switch_uint32(val); * `val` would need to be switched on a big endian system. */
#endif
return true; return true;
} }

View File

@ -70,11 +70,8 @@ struct md5_ctx {
md5_uint32 D; md5_uint32 D;
}; };
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
# define SWAP(n) (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #define SWAP(n) (n)
#else
# define SWAP(n) (n)
#endif
/* This array contains the bytes used to pad the buffer to the next 64-byte boundary. /* This array contains the bytes used to pad the buffer to the next 64-byte boundary.
* (RFC 1321, 3.1: Step 1) */ * (RFC 1321, 3.1: Step 1) */

View File

@ -721,11 +721,8 @@ static ushort hipart(const float f)
tmp.f = f; tmp.f = f;
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
return tmp.us[0];
#else
return tmp.us[1]; return tmp.us[1];
#endif
} }
static float index_to_float(const ushort i) static float index_to_float(const ushort i)
@ -748,13 +745,9 @@ static float index_to_float(const ushort i)
return -FLT_MAX; return -FLT_MAX;
} }
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
tmp.us[0] = i;
tmp.us[1] = 0x8000;
#else
tmp.us[0] = 0x8000; tmp.us[0] = 0x8000;
tmp.us[1] = i; tmp.us[1] = i;
#endif
return tmp.f; return tmp.f;
} }

View File

@ -108,11 +108,8 @@ MINLINE unsigned short to_srgb_table_lookup(const float f)
unsigned short us[2]; unsigned short us[2];
} tmp; } tmp;
tmp.f = f; tmp.f = f;
# ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
return BLI_color_to_srgb_table[tmp.us[0]];
# else
return BLI_color_to_srgb_table[tmp.us[1]]; return BLI_color_to_srgb_table[tmp.us[1]];
# endif
} }
MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4]) MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])

View File

@ -391,12 +391,9 @@ void RandomNumberGenerator::get_bytes(MutableSpan<char> r_bytes)
int64_t i = 0; int64_t i = 0;
while (i != trim_len) { while (i != trim_len) {
BLI_assert(i < trim_len); BLI_assert(i < trim_len);
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive.
for (int64_t j = (rand_stride + mask_bytes) - 1; j != mask_bytes - 1; j--) * Big Endian needs to iterate in reverse, with a `mask_bytes - 1` offset. */
#else for (int64_t j = 0; j != rand_stride; j++) {
for (int64_t j = 0; j != rand_stride; j++)
#endif
{
r_bytes[i++] = data_src[j]; r_bytes[i++] = data_src[j];
} }
this->step(); this->step();

View File

@ -26,6 +26,8 @@ TEST(BLI_build_config, Endian)
#if defined(__BIG_ENDIAN__) #if defined(__BIG_ENDIAN__)
static_assert(ARCH_CPU_BIG_ENDIAN); static_assert(ARCH_CPU_BIG_ENDIAN);
static_assert(!ARCH_CPU_LITTLE_ENDIAN); static_assert(!ARCH_CPU_LITTLE_ENDIAN);
/* Blender does not build on big endian systems. */
static_assert(0);
#endif #endif
#if defined(__LITTLE_ENDIAN__) #if defined(__LITTLE_ENDIAN__)
static_assert(!ARCH_CPU_BIG_ENDIAN); static_assert(!ARCH_CPU_BIG_ENDIAN);

View File

@ -19,11 +19,9 @@ TEST(hash_mm2a, MM2ABasic)
BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const uchar *)data, strlen(data)); BLI_hash_mm2a_add(&mm2, (const uchar *)data, strlen(data));
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* On BE systems, the expected value would be 959283772. */
EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145); EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145);
#else
EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 959283772);
#endif
} }
TEST(hash_mm2a, MM2AConcatenateStrings) TEST(hash_mm2a, MM2AConcatenateStrings)
@ -43,11 +41,9 @@ TEST(hash_mm2a, MM2AConcatenateStrings)
hash = BLI_hash_mm2a_end(&mm2); hash = BLI_hash_mm2a_end(&mm2);
BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const uchar *)data123, strlen(data123)); BLI_hash_mm2a_add(&mm2, (const uchar *)data123, strlen(data123));
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* On BE systems, the expected value would be 2604964730. */
EXPECT_EQ(hash, 1545105348); EXPECT_EQ(hash, 1545105348);
#else
EXPECT_EQ(hash, 2604964730);
#endif
EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash); EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash);
} }
@ -66,11 +62,8 @@ TEST(hash_mm2a, MM2AIntegers)
hash = BLI_hash_mm2a_end(&mm2); hash = BLI_hash_mm2a_end(&mm2);
BLI_hash_mm2a_init(&mm2, 0); BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const uchar *)ints, sizeof(ints)); BLI_hash_mm2a_add(&mm2, (const uchar *)ints, sizeof(ints));
/* Yes, same hash here on little and big endian. */ /* NOTE: this is endianness-sensitive. */
#ifdef __LITTLE_ENDIAN__ /* Actually, same hash here on little and big endian. */
EXPECT_EQ(hash, 405493096); EXPECT_EQ(hash, 405493096);
#else
EXPECT_EQ(hash, 405493096);
#endif
EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash); EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash);
} }

View File

@ -369,7 +369,6 @@ const blender::ImplicitSharingInfo *BLO_read_shared(
} }
int BLO_read_fileversion_get(BlendDataReader *reader); int BLO_read_fileversion_get(BlendDataReader *reader);
bool BLO_read_requires_endian_switch(BlendDataReader *reader);
bool BLO_read_data_is_undo(BlendDataReader *reader); bool BLO_read_data_is_undo(BlendDataReader *reader);
void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr); void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr);
void BLO_read_glob_list(BlendDataReader *reader, ListBase *list); void BLO_read_glob_list(BlendDataReader *reader, ListBase *list);

View File

@ -623,12 +623,11 @@ struct BlendLibReader {
static BHeadN *get_bhead(FileData *fd) static BHeadN *get_bhead(FileData *fd)
{ {
BHeadN *new_bhead = nullptr; BHeadN *new_bhead = nullptr;
const bool do_endian_swap = fd->flags & FD_FLAGS_SWITCH_ENDIAN;
if (fd) { if (fd) {
if (!fd->is_eof) { if (!fd->is_eof) {
std::optional<BHead> bhead_opt = BLO_readfile_read_bhead( std::optional<BHead> bhead_opt = BLO_readfile_read_bhead(fd->file,
fd->file, fd->blender_header.bhead_type(), do_endian_swap); fd->blender_header.bhead_type());
BHead *bhead = nullptr; BHead *bhead = nullptr;
if (!bhead_opt.has_value()) { if (!bhead_opt.has_value()) {
fd->is_eof = true; fd->is_eof = true;
@ -884,10 +883,9 @@ static bool read_file_dna(FileData *fd, const char **r_error_message)
subversion = atoi(num); subversion = atoi(num);
} }
else if (bhead->code == BLO_CODE_DNA1) { else if (bhead->code == BLO_CODE_DNA1) {
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0; BLI_assert((fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
const bool do_alias = false; /* Postpone until after #blo_do_versions_dna runs. */ const bool do_alias = false; /* Postpone until after #blo_do_versions_dna runs. */
fd->filesdna = DNA_sdna_from_data( fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, true, do_alias, r_error_message);
&bhead[1], bhead->len, do_endian_swap, true, do_alias, r_error_message);
if (fd->filesdna) { if (fd->filesdna) {
blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion); blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion);
/* Allow aliased lookups (must be after version patching DNA). */ /* Allow aliased lookups (must be after version patching DNA). */
@ -1200,7 +1198,18 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports)
{ {
read_blender_header(fd); read_blender_header(fd);
if (fd->flags & FD_FLAGS_FILE_OK) { if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
BKE_reportf(reports,
RPT_ERROR,
"Blend file '%s' created by a Big Endian version of Blender, support for "
"these files has been removed in Blender 5.0, use an older version of Blender "
"to open and convert it.",
fd->relabase);
blo_filedata_free(fd);
fd = nullptr;
}
else if (fd->flags & FD_FLAGS_FILE_OK) {
const char *error_message = nullptr; const char *error_message = nullptr;
if (read_file_dna(fd, &error_message) == false) { if (read_file_dna(fd, &error_message) == false) {
BKE_reportf( BKE_reportf(
@ -1212,22 +1221,6 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports)
blo_filedata_free(fd); blo_filedata_free(fd);
fd = nullptr; fd = nullptr;
} }
else if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
if (ENDIAN_ORDER == L_ENDIAN) {
if (!BKE_reports_print_test(reports, RPT_WARNING)) {
CLOG_WARN(
&LOG,
"Blend file '%s' created by a Big Endian version of Blender, support for these "
"files will be removed in Blender 5.0",
fd->relabase);
}
BKE_reportf(reports,
RPT_WARNING,
"Blend file '%s' created by a Big Endian version of Blender, support for "
"these files will be removed in Blender 5.0",
fd->relabase);
}
}
} }
else if (fd->flags & FD_FLAGS_FILE_FUTURE) { else if (fd->flags & FD_FLAGS_FILE_FUTURE) {
BKE_reportf( BKE_reportf(
@ -1784,23 +1777,6 @@ void blo_cache_storage_end(FileData *fd)
/** \name DNA Struct Loading /** \name DNA Struct Loading
* \{ */ * \{ */
static void switch_endian_structs(const SDNA *filesdna, BHead *bhead)
{
int blocksize, nblocks;
char *data;
data = (char *)(bhead + 1);
blocksize = DNA_struct_size(filesdna, bhead->SDNAnr);
nblocks = bhead->nr;
while (nblocks--) {
DNA_struct_switch_endian(filesdna, bhead->SDNAnr, data);
data += blocksize;
}
}
/** /**
* Generate the final allocation string reference for read blocks of data. If \a blockname is * Generate the final allocation string reference for read blocks of data. If \a blockname is
* given, use it as 'owner block' info, otherwise use the id type index to get that info. * given, use it as 'owner block' info, otherwise use the id type index to get that info.
@ -1897,6 +1873,7 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname, const i
* *
* NOTE: raw data (aka #SDNA_RAW_DATA_STRUCT_INDEX #SDNAnr) is not handled here, it's up to * NOTE: raw data (aka #SDNA_RAW_DATA_STRUCT_INDEX #SDNAnr) is not handled here, it's up to
* the calling code to manage this. */ * the calling code to manage this. */
BLI_assert((fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0") BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0")
if (bh->SDNAnr > SDNA_RAW_DATA_STRUCT_INDEX && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) { if (bh->SDNAnr > SDNA_RAW_DATA_STRUCT_INDEX && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
#ifdef USE_BHEAD_READ_ON_DEMAND #ifdef USE_BHEAD_READ_ON_DEMAND
@ -1908,7 +1885,6 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname, const i
} }
} }
#endif #endif
switch_endian_structs(fd->filesdna, bh);
} }
if (fd->compflags[bh->SDNAnr] != SDNA_CMP_REMOVED) { if (fd->compflags[bh->SDNAnr] != SDNA_CMP_REMOVED) {
@ -4764,6 +4740,8 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag, ReportL
/* FIXME This is extremely bad design, #library_link_end should probably _always_ free the file /* FIXME This is extremely bad design, #library_link_end should probably _always_ free the file
* data? */ * data? */
if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) { if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
/* Big Endian blendfiles are not supported for linking. */
BLI_assert_unreachable();
blo_filedata_free(*fd); blo_filedata_free(*fd);
*fd = nullptr; *fd = nullptr;
} }
@ -5229,11 +5207,6 @@ int BLO_read_fileversion_get(BlendDataReader *reader)
return reader->fd->fileversion; return reader->fd->fileversion;
} }
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
{
return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
}
void BLO_read_struct_list_with_size(BlendDataReader *reader, void BLO_read_struct_list_with_size(BlendDataReader *reader,
const size_t expected_elem_size, const size_t expected_elem_size,
ListBase *list) ListBase *list)
@ -5277,40 +5250,28 @@ void BLO_read_int16_array(BlendDataReader *reader, const int64_t array_size, int
{ {
*ptr_p = reinterpret_cast<int16_t *>( *ptr_p = reinterpret_cast<int16_t *>(
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int16_t) * array_size)); BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int16_t) * array_size));
BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int16_array(*ptr_p, array_size);
}
} }
void BLO_read_int32_array(BlendDataReader *reader, const int64_t array_size, int32_t **ptr_p) void BLO_read_int32_array(BlendDataReader *reader, const int64_t array_size, int32_t **ptr_p)
{ {
*ptr_p = reinterpret_cast<int32_t *>( *ptr_p = reinterpret_cast<int32_t *>(
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int32_t) * array_size)); BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int32_t) * array_size));
BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int32_array(*ptr_p, array_size);
}
} }
void BLO_read_uint32_array(BlendDataReader *reader, const int64_t array_size, uint32_t **ptr_p) void BLO_read_uint32_array(BlendDataReader *reader, const int64_t array_size, uint32_t **ptr_p)
{ {
*ptr_p = reinterpret_cast<uint32_t *>( *ptr_p = reinterpret_cast<uint32_t *>(
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint32_t) * array_size)); BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint32_t) * array_size));
BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_uint32_array(*ptr_p, array_size);
}
} }
void BLO_read_float_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p) void BLO_read_float_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p)
{ {
*ptr_p = reinterpret_cast<float *>( *ptr_p = reinterpret_cast<float *>(
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(float) * array_size)); BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(float) * array_size));
BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_float_array(*ptr_p, array_size);
}
} }
void BLO_read_float3_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p) void BLO_read_float3_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p)
@ -5322,10 +5283,7 @@ void BLO_read_double_array(BlendDataReader *reader, const int64_t array_size, do
{ {
*ptr_p = reinterpret_cast<double *>( *ptr_p = reinterpret_cast<double *>(
BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(double) * array_size)); BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(double) * array_size));
BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
if (*ptr_p && BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_double_array(*ptr_p, array_size);
}
} }
void BLO_read_string(BlendDataReader *reader, char **ptr_p) void BLO_read_string(BlendDataReader *reader, char **ptr_p)
@ -5362,9 +5320,9 @@ static void convert_pointer_array_64_to_32(BlendDataReader *reader,
const uint64_t *src, const uint64_t *src,
uint32_t *dst) uint32_t *dst)
{ {
const bool use_endian_swap = BLO_read_requires_endian_switch(reader); BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
for (int i = 0; i < array_size; i++) { for (int i = 0; i < array_size; i++) {
dst[i] = uint32_from_uint64_ptr(src[i], use_endian_swap); dst[i] = uint32_from_uint64_ptr(src[i]);
} }
} }

View File

@ -12,12 +12,13 @@
* *
* IFF-style structure (but not IFF compatible!) * IFF-style structure (but not IFF compatible!)
* *
* Start file: * Start of the file:
* <pre> *
* `BLENDER_V100` `12` bytes (version 1.00 is just an example). * Historic Blendfiles (pre-Blender 5.0):
* `V` = big endian, `v` = little endian. * `BLENDER_V100` : Fixed 12 bytes length. See #BLEND_FILE_FORMAT_VERSION_0 for details.
* `_` = 4 byte pointer, `-` = 8 byte pointer. *
* </pre> * Current Blendfiles (Blender 5.0 and later):
* `BLENDER17-01v0500`: Variable bytes length. See #BLEND_FILE_FORMAT_VERSION_1 for details.
* *
* data-blocks: (also see struct #BHead). * data-blocks: (also see struct #BHead).
* <pre> * <pre>
@ -92,7 +93,6 @@
#include "DNA_userdef_types.h" #include "DNA_userdef_types.h"
#include "BLI_endian_defines.h" #include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_fileops.hh" #include "BLI_fileops.hh"
#include "BLI_implicit_sharing.hh" #include "BLI_implicit_sharing.hh"
#include "BLI_math_base.h" #include "BLI_math_base.h"
@ -312,9 +312,9 @@ bool ZstdWriteWrap::open(const char *filepath)
void ZstdWriteWrap::write_u32_le(uint32_t val) void ZstdWriteWrap::write_u32_le(uint32_t val)
{ {
if (ENDIAN_ORDER == B_ENDIAN) { /* NOTE: this is endianness-sensitive.
BLI_endian_switch_uint32(&val); * This value must always be written as little-endian. */
} BLI_assert(ENDIAN_ORDER == L_ENDIAN);
base_wrap.write(&val, sizeof(uint32_t)); base_wrap.write(&val, sizeof(uint32_t));
} }
@ -1380,7 +1380,7 @@ static std::string get_blend_file_header()
} }
const char pointer_size_char = sizeof(void *) == 8 ? '-' : '_'; const char pointer_size_char = sizeof(void *) == 8 ? '-' : '_';
const char endian_char = ENDIAN_ORDER == B_ENDIAN ? 'V' : 'v'; const char endian_char = 'v';
/* Legacy blend file header format. */ /* Legacy blend file header format. */
std::stringstream ss; std::stringstream ss;

View File

@ -111,9 +111,7 @@ enum {
* *
* \return The next #BHEad or #std::nullopt if the file is exhausted. * \return The next #BHEad or #std::nullopt if the file is exhausted.
*/ */
std::optional<BHead> BLO_readfile_read_bhead(FileReader *file, std::optional<BHead> BLO_readfile_read_bhead(FileReader *file, BHeadType type);
BHeadType type,
bool do_endian_swap);
/** /**
* Converts a BHead.old pointer from 64 to 32 bit. This can't work in the general case, but only * Converts a BHead.old pointer from 64 to 32 bit. This can't work in the general case, but only
@ -121,12 +119,11 @@ std::optional<BHead> BLO_readfile_read_bhead(FileReader *file,
* pointers will map to the same, which will break things later on. There is no way to check for * pointers will map to the same, which will break things later on. There is no way to check for
* that here unfortunately. * that here unfortunately.
*/ */
inline uint32_t uint32_from_uint64_ptr(uint64_t ptr, const bool use_endian_swap) inline uint32_t uint32_from_uint64_ptr(uint64_t ptr)
{ {
if (use_endian_swap) { /* NOTE: this is endianness-sensitive. */
/* Do endian switch so that the resulting pointer is not all 0. */ /* Switching endianess would be required to reduce the risk of two different 64bits pointers
BLI_endian_switch_uint64(&ptr); * generating the same 32bits value. */
}
/* Behavior has to match #cast_pointer_64_to_32. */ /* Behavior has to match #cast_pointer_64_to_32. */
ptr >>= 3; ptr >>= 3;
return uint32_t(ptr); return uint32_t(ptr);

View File

@ -6,48 +6,6 @@
#include "BLO_core_bhead.hh" #include "BLO_core_bhead.hh"
static void switch_endian_bh4(BHead4 *bhead)
{
/* the ID_.. codes */
if ((bhead->code & 0xFFFF) == 0) {
bhead->code >>= 16;
}
if (bhead->code != BLO_CODE_ENDB) {
BLI_endian_switch_int32(&bhead->len);
BLI_endian_switch_int32(&bhead->SDNAnr);
BLI_endian_switch_int32(&bhead->nr);
}
}
static void switch_endian_small_bh8(SmallBHead8 *bhead)
{
/* The ID_* codes. */
if ((bhead->code & 0xFFFF) == 0) {
bhead->code >>= 16;
}
if (bhead->code != BLO_CODE_ENDB) {
BLI_endian_switch_int32(&bhead->len);
BLI_endian_switch_int32(&bhead->SDNAnr);
BLI_endian_switch_int32(&bhead->nr);
}
}
static void switch_endian_large_bh8(LargeBHead8 *bhead)
{
/* The ID_* codes. */
if ((bhead->code & 0xFFFF) == 0) {
bhead->code >>= 16;
}
if (bhead->code != BLO_CODE_ENDB) {
BLI_endian_switch_int64(&bhead->len);
BLI_endian_switch_int32(&bhead->SDNAnr);
BLI_endian_switch_int64(&bhead->nr);
}
}
static BHead bhead_from_bhead4(const BHead4 &bhead4) static BHead bhead_from_bhead4(const BHead4 &bhead4)
{ {
BHead bhead; BHead bhead;
@ -59,51 +17,49 @@ static BHead bhead_from_bhead4(const BHead4 &bhead4)
return bhead; return bhead;
} }
static const void *old_ptr_from_uint64_ptr(const uint64_t ptr, const bool use_endian_swap) static const void *old_ptr_from_uint64_ptr(const uint64_t ptr)
{ {
if constexpr (sizeof(void *) == 8) { if constexpr (sizeof(void *) == 8) {
return reinterpret_cast<const void *>(ptr); return reinterpret_cast<const void *>(ptr);
} }
else { else {
return reinterpret_cast<const void *>(uintptr_t(uint32_from_uint64_ptr(ptr, use_endian_swap))); return reinterpret_cast<const void *>(uintptr_t(uint32_from_uint64_ptr(ptr)));
} }
} }
static BHead bhead_from_small_bhead8(const SmallBHead8 &small_bhead8, const bool use_endian_swap) static BHead bhead_from_small_bhead8(const SmallBHead8 &small_bhead8)
{ {
BHead bhead; BHead bhead;
bhead.code = small_bhead8.code; bhead.code = small_bhead8.code;
bhead.len = small_bhead8.len; bhead.len = small_bhead8.len;
bhead.old = old_ptr_from_uint64_ptr(small_bhead8.old, use_endian_swap); bhead.old = old_ptr_from_uint64_ptr(small_bhead8.old);
bhead.SDNAnr = small_bhead8.SDNAnr; bhead.SDNAnr = small_bhead8.SDNAnr;
bhead.nr = small_bhead8.nr; bhead.nr = small_bhead8.nr;
return bhead; return bhead;
} }
static BHead bhead_from_large_bhead8(const LargeBHead8 &large_bhead8, const bool use_endian_swap) static BHead bhead_from_large_bhead8(const LargeBHead8 &large_bhead8)
{ {
BHead bhead; BHead bhead;
bhead.code = large_bhead8.code; bhead.code = large_bhead8.code;
bhead.len = large_bhead8.len; bhead.len = large_bhead8.len;
bhead.old = old_ptr_from_uint64_ptr(large_bhead8.old, use_endian_swap); bhead.old = old_ptr_from_uint64_ptr(large_bhead8.old);
bhead.SDNAnr = large_bhead8.SDNAnr; bhead.SDNAnr = large_bhead8.SDNAnr;
bhead.nr = large_bhead8.nr; bhead.nr = large_bhead8.nr;
return bhead; return bhead;
} }
std::optional<BHead> BLO_readfile_read_bhead(FileReader *file, std::optional<BHead> BLO_readfile_read_bhead(FileReader *file, const BHeadType type)
const BHeadType type,
const bool do_endian_swap)
{ {
/* NOTE: this is endianness-sensitive. */
/* The various BHead data below would need to be switched if the read blend-file was saved from a
* system using a different endianness. */
switch (type) { switch (type) {
case BHeadType::BHead4: { case BHeadType::BHead4: {
BHead4 bhead4{}; BHead4 bhead4{};
bhead4.code = BLO_CODE_DATA; bhead4.code = BLO_CODE_DATA;
const int64_t readsize = file->read(file, &bhead4, sizeof(bhead4)); const int64_t readsize = file->read(file, &bhead4, sizeof(bhead4));
if (readsize == sizeof(bhead4) || bhead4.code == BLO_CODE_ENDB) { if (readsize == sizeof(bhead4) || bhead4.code == BLO_CODE_ENDB) {
if (do_endian_swap) {
switch_endian_bh4(&bhead4);
}
return bhead_from_bhead4(bhead4); return bhead_from_bhead4(bhead4);
} }
break; break;
@ -113,10 +69,7 @@ std::optional<BHead> BLO_readfile_read_bhead(FileReader *file,
small_bhead8.code = BLO_CODE_DATA; small_bhead8.code = BLO_CODE_DATA;
const int64_t readsize = file->read(file, &small_bhead8, sizeof(small_bhead8)); const int64_t readsize = file->read(file, &small_bhead8, sizeof(small_bhead8));
if (readsize == sizeof(small_bhead8) || small_bhead8.code == BLO_CODE_ENDB) { if (readsize == sizeof(small_bhead8) || small_bhead8.code == BLO_CODE_ENDB) {
if (do_endian_swap) { return bhead_from_small_bhead8(small_bhead8);
switch_endian_small_bh8(&small_bhead8);
}
return bhead_from_small_bhead8(small_bhead8, do_endian_swap);
} }
break; break;
} }
@ -125,10 +78,7 @@ std::optional<BHead> BLO_readfile_read_bhead(FileReader *file,
large_bhead8.code = BLO_CODE_DATA; large_bhead8.code = BLO_CODE_DATA;
const int64_t readsize = file->read(file, &large_bhead8, sizeof(large_bhead8)); const int64_t readsize = file->read(file, &large_bhead8, sizeof(large_bhead8));
if (readsize == sizeof(large_bhead8) || large_bhead8.code == BLO_CODE_ENDB) { if (readsize == sizeof(large_bhead8) || large_bhead8.code == BLO_CODE_ENDB) {
if (do_endian_swap) { return bhead_from_large_bhead8(large_bhead8);
switch_endian_large_bh8(&large_bhead8);
}
return bhead_from_large_bhead8(large_bhead8, do_endian_swap);
} }
break; break;
} }

View File

@ -63,11 +63,9 @@ class Precompute {
file.open(std::string(name) + ".pfm"); file.open(std::string(name) + ".pfm");
file << "PF\n"; file << "PF\n";
file << n_x * n_z << " " << n_y * n_w << "\n"; file << n_x * n_z << " " << n_y * n_w << "\n";
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive.
* Big endian system would have needed `1.0` value instead. */
file << "-1.0\n"; file << "-1.0\n";
#else
file << "1.0\n";
#endif
file.close(); file.close();
/* Write binary float content. */ /* Write binary float content. */

View File

@ -740,13 +740,10 @@ cache_end:
union { union {
uint32_t as_u32; uint32_t as_u32;
struct { struct {
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive.
uint16_t ob; * In Big Endian the order of these two variable would have to be inverted. */
uint16_t bone;
#else
uint16_t bone; uint16_t bone;
uint16_t ob; uint16_t ob;
#endif
}; };
} offset, test, best; } offset, test, best;
} cycle_order; } cycle_order;

View File

@ -38,10 +38,6 @@
#include "BLT_translation.hh" #include "BLT_translation.hh"
#ifdef __BIG_ENDIAN__
# include "BLI_endian_switch.h"
#endif
#include "BKE_action.hh" #include "BKE_action.hh"
#include "BKE_armature.hh" #include "BKE_armature.hh"
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
@ -2238,14 +2234,11 @@ static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b
} }
/* Depths match, sort by id. */ /* Depths match, sort by id. */
/* NOTE: this is endianness-sensitive.
* GPUSelectResult values are always expected to be little-endian. */
uint sel_a = a->id; uint sel_a = a->id;
uint sel_b = b->id; uint sel_b = b->id;
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&sel_a);
BLI_endian_switch_uint32(&sel_b);
#endif
if (sel_a < sel_b) { if (sel_a < sel_b) {
return -1; return -1;
} }
@ -4225,14 +4218,11 @@ static bool do_armature_box_select(const ViewContext *vc, const rcti *rect, cons
*/ */
static int gpu_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p) static int gpu_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
{ {
/* NOTE: this is endianness-sensitive.
* GPUSelectResult values are always expected to be little-endian. */
uint sel_a = ((GPUSelectResult *)sel_a_p)->id; uint sel_a = ((GPUSelectResult *)sel_a_p)->id;
uint sel_b = ((GPUSelectResult *)sel_b_p)->id; uint sel_b = ((GPUSelectResult *)sel_b_p)->id;
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&sel_a);
BLI_endian_switch_uint32(&sel_b);
#endif
if (sel_a < sel_b) { if (sel_a < sel_b) {
return -1; return -1;
} }

View File

@ -21,10 +21,6 @@
#include "BLI_path_utils.hh" #include "BLI_path_utils.hh"
#include "BLI_string.h" #include "BLI_string.h"
#ifdef __BIG_ENDIAN__
# include "BLI_endian_switch.h"
#endif
OIIO_NAMESPACE_USING OIIO_NAMESPACE_USING
using namespace blender::imbuf; using namespace blender::imbuf;
@ -307,13 +303,11 @@ static void LoadDXTCImage(ImBuf *ibuf, Filesystem::IOMemReader &mem_reader)
* we've made it this far. */ * we've made it this far. */
uint32_t flags = 0; uint32_t flags = 0;
mem_reader.pread(&flags, sizeof(uint32_t), 8); mem_reader.pread(&flags, sizeof(uint32_t), 8);
/* NOTE: this is endianness-sensitive. */
/* `ibuf->dds_data.nummipmaps` is always expected to be little-endian. */
mem_reader.pread(&ibuf->dds_data.nummipmaps, sizeof(uint32_t), 28); mem_reader.pread(&ibuf->dds_data.nummipmaps, sizeof(uint32_t), 28);
mem_reader.pread(&ibuf->dds_data.fourcc, sizeof(uint32_t), 84); mem_reader.pread(&ibuf->dds_data.fourcc, sizeof(uint32_t), 84);
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&ibuf->dds_data.nummipmaps);
#endif
const uint32_t DDSD_MIPMAPCOUNT = 0x00020000U; const uint32_t DDSD_MIPMAPCOUNT = 0x00020000U;
if ((flags & DDSD_MIPMAPCOUNT) == 0) { if ((flags & DDSD_MIPMAPCOUNT) == 0) {
ibuf->dds_data.nummipmaps = 1; ibuf->dds_data.nummipmaps = 1;

View File

@ -83,7 +83,9 @@ static MovieIndexBuilder *index_builder_create(const char *filepath)
fprintf(rv->fp, fprintf(rv->fp,
"%s%c%.3d", "%s%c%.3d",
binary_header_str, binary_header_str,
(ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v', /* NOTE: this is endianness-sensitive.
* On Big Endian system 'V' must be used instead of 'v'. */
'v',
INDEX_FILE_VERSION); INDEX_FILE_VERSION);
return rv; return rv;
@ -179,7 +181,10 @@ static MovieIndex *movie_index_open(const char *filepath)
return nullptr; return nullptr;
} }
if ((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V')) { /* NOTE: this is endianness-sensitive. */
BLI_assert(ELEM(header[8], 'v', 'V'));
const int16_t file_endianness = (header[8] == 'v') ? L_ENDIAN : B_ENDIAN;
if (file_endianness == B_ENDIAN) {
for (int64_t i = 0; i < num_entries; i++) { for (int64_t i = 0; i < num_entries; i++) {
BLI_endian_switch_int32(&idx->entries[i].frameno); BLI_endian_switch_int32(&idx->entries[i].frameno);
BLI_endian_switch_uint64(&idx->entries[i].seek_pos_pts); BLI_endian_switch_uint64(&idx->entries[i].seek_pos_pts);

View File

@ -21,7 +21,6 @@
# include "MEM_guardedalloc.h" # include "MEM_guardedalloc.h"
# include "BLI_endian_defines.h"
# include "BLI_fileops.h" # include "BLI_fileops.h"
# include "BLI_math_base.h" # include "BLI_math_base.h"
# include "BLI_path_utils.hh" # include "BLI_path_utils.hh"
@ -254,30 +253,15 @@ static AVFrame *generate_video_frame(MovieWriter *context, const ImBuf *image)
} }
} }
else { else {
/* Byte image: flip the image vertically, possibly with endian /* Byte image: flip the image vertically. */
* conversion. */
const size_t linesize_src = rgb_frame->width * 4; const size_t linesize_src = rgb_frame->width * 4;
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
uint8_t *target = rgb_frame->data[0] + linesize_dst * (height - y - 1); uint8_t *target = rgb_frame->data[0] + linesize_dst * (height - y - 1);
const uint8_t *src = pixels + linesize_src * y; const uint8_t *src = pixels + linesize_src * y;
# if ENDIAN_ORDER == L_ENDIAN /* NOTE: this is endianness-sensitive. */
/* The target buffer is always expected to conaint little-endian RGBA values. */
memcpy(target, src, linesize_src); memcpy(target, src, linesize_src);
# elif ENDIAN_ORDER == B_ENDIAN
const uint8_t *end = src + linesize_src;
while (src != end) {
target[3] = src[0];
target[2] = src[1];
target[1] = src[2];
target[0] = src[3];
target += 4;
src += 4;
}
# else
# error ENDIAN_ORDER should either be L_ENDIAN or B_ENDIAN.
# endif
} }
} }

View File

@ -97,14 +97,8 @@ typedef enum eIDPropertyFlag {
* The tags represent types! This is a dirty way of enabling RTTI. The * The tags represent types! This is a dirty way of enabling RTTI. The
* sig_byte end endian defines aren't really used much. * sig_byte end endian defines aren't really used much.
*/ */
/* NOTE: this is endianness-sensitive. */
#ifdef __BIG_ENDIAN__ #define MAKE_ID2(c, d) ((d) << 8 | (c))
/* big endian */
# define MAKE_ID2(c, d) ((c) << 8 | (d))
#else
/* little endian */
# define MAKE_ID2(c, d) ((d) << 8 | (c))
#endif
/** /**
* ID from database. * ID from database.

View File

@ -24,10 +24,11 @@ extern const int DNAlen;
/** /**
* Primitive (non-struct, non-pointer/function/array) types, * Primitive (non-struct, non-pointer/function/array) types,
*
* NOTE: this is endianness-sensitive.
* \warning Don't change these values! * \warning Don't change these values!
* Currently changes here will work on native endianness, * Currently changes here will work on native endianness, however before 5.0,
* however #DNA_struct_switch_endian currently checks these * #DNA_struct_switch_endian used to check these hard-coded values against those from old files.
* hard-coded values against those from old files.
*/ */
typedef enum eSDNA_Type { typedef enum eSDNA_Type {
SDNA_TYPE_CHAR = 0, SDNA_TYPE_CHAR = 0,
@ -61,8 +62,7 @@ enum eSDNA_StructCompare {
/* Struct has disappeared /* Struct has disappeared
* (values of this struct type will not be loaded by the current Blender) */ * (values of this struct type will not be loaded by the current Blender) */
SDNA_CMP_REMOVED = 0, SDNA_CMP_REMOVED = 0,
/* Struct is the same /* Struct is the same (can be loaded with straight memory copy). */
* (can be loaded with straight memory copy after any necessary endian conversion) */
SDNA_CMP_EQUAL = 1, SDNA_CMP_EQUAL = 1,
/* Struct is different in some way /* Struct is different in some way
* (needs to be copied/converted field by field) */ * (needs to be copied/converted field by field) */
@ -74,12 +74,8 @@ enum eSDNA_StructCompare {
/** /**
* Constructs and returns a decoded SDNA structure from the given encoded SDNA data block. * Constructs and returns a decoded SDNA structure from the given encoded SDNA data block.
*/ */
struct SDNA *DNA_sdna_from_data(const void *data, struct SDNA *DNA_sdna_from_data(
int data_len, const void *data, int data_len, bool data_alloc, bool do_alias, const char **r_error_message);
bool do_endian_swap,
bool data_alloc,
bool do_alias,
const char **r_error_message);
void DNA_sdna_free(struct SDNA *sdna); void DNA_sdna_free(struct SDNA *sdna);
/* Access for current Blender versions SDNA. */ /* Access for current Blender versions SDNA. */
@ -137,14 +133,6 @@ bool DNA_struct_member_exists_without_alias(const struct SDNA *sdna,
const char *vartype, const char *vartype,
const char *name); const char *name);
/**
* Does endian swapping on the fields of a struct value.
*
* \param sdna: SDNA of the struct_nr belongs to
* \param struct_nr: Index of struct info within sdna
* \param data: Struct data that is to be converted
*/
void DNA_struct_switch_endian(const struct SDNA *sdna, int struct_index, char *data);
/** /**
* Constructs and returns an array of byte flags with one element for each struct in oldsdna, * Constructs and returns an array of byte flags with one element for each struct in oldsdna,
* indicating how it compares to newsdna. * indicating how it compares to newsdna.

View File

@ -53,7 +53,6 @@ set(BLENLIB_SRC
../../blenlib/intern/BLI_linklist.cc ../../blenlib/intern/BLI_linklist.cc
../../blenlib/intern/BLI_memarena.cc ../../blenlib/intern/BLI_memarena.cc
../../blenlib/intern/BLI_mempool.cc ../../blenlib/intern/BLI_mempool.cc
../../blenlib/intern/endian_switch.cc
../../blenlib/intern/listbase.cc ../../blenlib/intern/listbase.cc
../../blenlib/intern/string.cc ../../blenlib/intern/string.cc

View File

@ -69,7 +69,6 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
#include "BLI_math_base.h" #include "BLI_math_base.h"
#include "BLI_math_rotation.h" #include "BLI_math_rotation.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"

View File

@ -23,7 +23,6 @@
#include "MEM_guardedalloc.h" /* for MEM_freeN MEM_mallocN MEM_callocN */ #include "MEM_guardedalloc.h" /* for MEM_freeN MEM_mallocN MEM_callocN */
#include "BLI_endian_switch.h"
#include "BLI_ghash.h" #include "BLI_ghash.h"
#include "BLI_index_range.hh" #include "BLI_index_range.hh"
#include "BLI_math_matrix_types.hh" #include "BLI_math_matrix_types.hh"
@ -42,8 +41,8 @@
* - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`. * - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`.
* *
* Structure DNA data is added to each blender file and to each executable, this to detect * Structure DNA data is added to each blender file and to each executable, this to detect
* in .blend files new variables in structs, changed array sizes, etc. It's also used for * in .blend files new variables in structs, changed array sizes, etc. It is also used for
* converting endian and pointer size (32-64 bits) * converting pointer size (32-64 bits) (and it used to be to handle endianness).
* As an extra, Python uses a call to detect run-time the contents of a blender struct. * As an extra, Python uses a call to detect run-time the contents of a blender struct.
* *
* Create a structDNA: only needed when one of the input include (.h) files change. * Create a structDNA: only needed when one of the input include (.h) files change.
@ -95,7 +94,6 @@
* - array (`vec[3]`) to float struct (`vec3f`). * - array (`vec[3]`) to float struct (`vec3f`).
* *
* DONE: * DONE:
* - Endian compatibility.
* - Pointer conversion (32-64 bits). * - Pointer conversion (32-64 bits).
* *
* IMPORTANT: * IMPORTANT:
@ -117,13 +115,9 @@
* always check blender running from a console. * always check blender running from a console.
*/ */
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* Big Endian */
# define MAKE_ID(a, b, c, d) (int(a) << 24 | int(b) << 16 | (c) << 8 | (d))
#else
/* Little Endian */ /* Little Endian */
# define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a)) #define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
#endif
/* ************************* DIV ********************** */ /* ************************* DIV ********************** */
@ -322,7 +316,7 @@ BLI_INLINE const char *pad_up_4(const char *ptr)
/** /**
* In sdna->data the data, now we convert that to something understandable * In sdna->data the data, now we convert that to something understandable
*/ */
static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error_message) static bool init_structDNA(SDNA *sdna, const char **r_error_message)
{ {
int member_index_gravity_fix = -1; int member_index_gravity_fix = -1;
@ -358,10 +352,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
if (*data == MAKE_ID('N', 'A', 'M', 'E')) { if (*data == MAKE_ID('N', 'A', 'M', 'E')) {
data++; data++;
/* NOTE: this is endianness-sensitive. */
sdna->members_num = *data; sdna->members_num = *data;
if (do_endian_swap) {
BLI_endian_switch_int32(&sdna->members_num);
}
sdna->members_num_alloc = sdna->members_num; sdna->members_num_alloc = sdna->members_num;
data++; data++;
@ -398,10 +390,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
if (*data == MAKE_ID('T', 'Y', 'P', 'E')) { if (*data == MAKE_ID('T', 'Y', 'P', 'E')) {
data++; data++;
/* NOTE: this is endianness-sensitive. */
sdna->types_num = *data; sdna->types_num = *data;
if (do_endian_swap) {
BLI_endian_switch_int32(&sdna->types_num);
}
data++; data++;
sdna->types = MEM_calloc_arrayN<const char *>(sdna->types_num, "sdnatypes"); sdna->types = MEM_calloc_arrayN<const char *>(sdna->types_num, "sdnatypes");
@ -428,13 +418,10 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
short *sp; short *sp;
if (*data == MAKE_ID('T', 'L', 'E', 'N')) { if (*data == MAKE_ID('T', 'L', 'E', 'N')) {
data++; data++;
/* NOTE: this is endianness-sensitive. */
sp = (short *)data; sp = (short *)data;
sdna->types_size = sp; sdna->types_size = sp;
if (do_endian_swap) {
BLI_endian_switch_int16_array(sp, sdna->types_num);
}
sp += sdna->types_num; sp += sdna->types_num;
} }
if (!sdna->types_size) { if (!sdna->types_size) {
@ -451,10 +438,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
if (*data == MAKE_ID('S', 'T', 'R', 'C')) { if (*data == MAKE_ID('S', 'T', 'R', 'C')) {
data++; data++;
/* NOTE: this is endianness-sensitive. */
sdna->structs_num = *data; sdna->structs_num = *data;
if (do_endian_swap) {
BLI_endian_switch_int32(&sdna->structs_num);
}
data++; data++;
sdna->structs = MEM_calloc_arrayN<SDNA_Struct *>(sdna->structs_num, "sdnastrcs"); sdna->structs = MEM_calloc_arrayN<SDNA_Struct *>(sdna->structs_num, "sdnastrcs");
@ -468,19 +453,10 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
blender::Set<short> struct_indices; blender::Set<short> struct_indices;
sp = (short *)data; sp = (short *)data;
for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) { for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
/* NOTE: this is endianness-sensitive. */
SDNA_Struct *struct_info = (SDNA_Struct *)sp; SDNA_Struct *struct_info = (SDNA_Struct *)sp;
sdna->structs[struct_index] = struct_info; sdna->structs[struct_index] = struct_info;
if (do_endian_swap) {
BLI_endian_switch_int16(&struct_info->type_index);
BLI_endian_switch_int16(&struct_info->members_num);
for (short a = 0; a < struct_info->members_num; a++) {
SDNA_StructMember *member = &struct_info->members[a];
BLI_endian_switch_int16(&member->type_index);
BLI_endian_switch_int16(&member->member_index);
}
}
if (!struct_indices.add(struct_info->type_index)) { if (!struct_indices.add(struct_info->type_index)) {
*r_error_message = "Invalid duplicate struct type index in SDNA file"; *r_error_message = "Invalid duplicate struct type index in SDNA file";
return false; return false;
@ -572,7 +548,6 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
SDNA *DNA_sdna_from_data(const void *data, SDNA *DNA_sdna_from_data(const void *data,
const int data_len, const int data_len,
bool do_endian_swap,
bool data_alloc, bool data_alloc,
const bool do_alias, const bool do_alias,
const char **r_error_message) const char **r_error_message)
@ -591,7 +566,7 @@ SDNA *DNA_sdna_from_data(const void *data,
} }
sdna->data_alloc = data_alloc; sdna->data_alloc = data_alloc;
if (init_structDNA(sdna, do_endian_swap, &error_message)) { if (init_structDNA(sdna, &error_message)) {
if (do_alias) { if (do_alias) {
DNA_sdna_alias_data_ensure_structs_map(sdna); DNA_sdna_alias_data_ensure_structs_map(sdna);
} }
@ -618,7 +593,7 @@ static SDNA *g_sdna = nullptr;
void DNA_sdna_current_init() void DNA_sdna_current_init()
{ {
g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, true, nullptr); g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, true, nullptr);
} }
const SDNA *DNA_sdna_current_get() const SDNA *DNA_sdna_current_get()
@ -755,7 +730,8 @@ const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna
* - `struct Link` never needed DNA-versioning. * - `struct Link` never needed DNA-versioning.
* *
* NOTE: This may have been broken in BE/LE conversion cases, however this endianness handling * NOTE: This may have been broken in BE/LE conversion cases, however this endianness handling
* code have likely been dead/never used in practice for many years now. * code have likely been dead/never used in practice for many years, and has been removed in
* Blender 5.0.
*/ */
BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0") BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0")
compare_flags[SDNA_RAW_DATA_STRUCT_INDEX] = SDNA_CMP_EQUAL; compare_flags[SDNA_RAW_DATA_STRUCT_INDEX] = SDNA_CMP_EQUAL;
@ -1115,74 +1091,6 @@ static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *m
return type_size * array_length; return type_size * array_length;
} }
void DNA_struct_switch_endian(const SDNA *sdna, int struct_index, char *data)
{
if (struct_index == -1) {
return;
}
const SDNA_Struct *struct_info = sdna->structs[struct_index];
int offset_in_bytes = 0;
for (int member_index = 0; member_index < struct_info->members_num; member_index++) {
const SDNA_StructMember *member = &struct_info->members[member_index];
const eStructMemberCategory member_category = get_struct_member_category(sdna, member);
char *member_data = data + offset_in_bytes;
const char *member_type_name = sdna->types[member->type_index];
const int member_array_length = sdna->members_array_num[member->member_index];
switch (member_category) {
case STRUCT_MEMBER_CATEGORY_STRUCT: {
const int substruct_size = sdna->types_size[member->type_index];
const int substruct_index = DNA_struct_find_index_without_alias(sdna, member_type_name);
BLI_assert(substruct_index != -1);
for (int a = 0; a < member_array_length; a++) {
DNA_struct_switch_endian(sdna, substruct_index, member_data + a * substruct_size);
}
break;
}
case STRUCT_MEMBER_CATEGORY_PRIMITIVE: {
switch (member->type_index) {
case SDNA_TYPE_SHORT:
case SDNA_TYPE_USHORT: {
BLI_endian_switch_int16_array((int16_t *)member_data, member_array_length);
break;
}
case SDNA_TYPE_INT:
case SDNA_TYPE_FLOAT: {
/* NOTE: intentionally ignore `long/ulong`, because these could be 4 or 8 bytes.
* Fortunately, we only use these types for runtime variables and only once for a
* struct type that is no longer used. */
BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length);
break;
}
case SDNA_TYPE_INT64:
case SDNA_TYPE_UINT64:
case SDNA_TYPE_DOUBLE: {
BLI_endian_switch_int64_array((int64_t *)member_data, member_array_length);
break;
}
default: {
break;
}
}
break;
}
case STRUCT_MEMBER_CATEGORY_POINTER: {
/* See `readfile.cc` (#uint32_from_uint64_ptr swap endian argument),
* this is only done when reducing the size of a pointer from 4 to 8. */
if (sizeof(void *) < 8) {
if (sdna->pointer_size == 8) {
BLI_endian_switch_uint64_array((uint64_t *)member_data, member_array_length);
}
}
break;
}
}
offset_in_bytes += get_member_size_in_bytes(sdna, member);
}
}
enum eReconstructStepType { enum eReconstructStepType {
RECONSTRUCT_STEP_MEMCPY, RECONSTRUCT_STEP_MEMCPY,
RECONSTRUCT_STEP_CAST_PRIMITIVE, RECONSTRUCT_STEP_CAST_PRIMITIVE,

View File

@ -707,7 +707,7 @@ BlenderRNA *RNA_create()
/* We need both alias and static (on-disk) DNA names. */ /* We need both alias and static (on-disk) DNA names. */
const bool do_alias = true; const bool do_alias = true;
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, do_alias, &error_message); DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, do_alias, &error_message);
if (DefRNA.sdna == nullptr) { if (DefRNA.sdna == nullptr) {
CLOG_ERROR(&LOG, "Failed to decode SDNA: %s.", error_message); CLOG_ERROR(&LOG, "Failed to decode SDNA: %s.", error_message);
DefRNA.error = true; DefRNA.error = true;

View File

@ -11,11 +11,9 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include "BLI_endian_switch.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_math_base.h" #include "BLI_math_base.h"
#ifdef __LITTLE_ENDIAN__
# include "BLI_endian_switch.h"
#endif
#ifdef WIN32 #ifdef WIN32
# include "BLI_winstuff.h" # include "BLI_winstuff.h"
#endif #endif
@ -41,9 +39,9 @@ static bool meshcache_read_mdd_head(FILE *fp,
return false; return false;
} }
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* MDD is big-endian, its values need to be switched on little-endian systems. */
BLI_endian_switch_int32_array((int *)mdd_head, 2); BLI_endian_switch_int32_array((int *)mdd_head, 2);
#endif
if (mdd_head->verts_tot != verts_tot) { if (mdd_head->verts_tot != verts_tot) {
*r_err_str = RPT_("Vertex count mismatch"); *r_err_str = RPT_("Vertex count mismatch");
@ -104,9 +102,10 @@ static bool meshcache_read_mdd_range_from_time(FILE *fp,
errno = 0; errno = 0;
for (i = 0; i < mdd_head.frame_tot; i++) { for (i = 0; i < mdd_head.frame_tot; i++) {
frames_num_read += fread(&f_time, sizeof(float), 1, fp); frames_num_read += fread(&f_time, sizeof(float), 1, fp);
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* MDD is big-endian, its values need to be switched on little-endian systems. */
BLI_endian_switch_float(&f_time); BLI_endian_switch_float(&f_time);
#endif
if (f_time >= time) { if (f_time >= time) {
frames_num_expect = i + 1; frames_num_expect = i + 1;
break; break;
@ -169,11 +168,11 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) { for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) {
verts_read_num += fread(vco, sizeof(float[3]), 1, fp); verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
# ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* MDD is big-endian, its values need to be switched on little-endian systems. */
BLI_endian_switch_float(vco + 0); BLI_endian_switch_float(vco + 0);
BLI_endian_switch_float(vco + 1); BLI_endian_switch_float(vco + 1);
BLI_endian_switch_float(vco + 2); BLI_endian_switch_float(vco + 2);
# endif /* __LITTLE_ENDIAN__ */
} }
#else #else
/* no blending */ /* no blending */
@ -181,9 +180,9 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
*r_err_str = errno ? strerror(errno) : RPT_("Failed to read frame"); *r_err_str = errno ? strerror(errno) : RPT_("Failed to read frame");
return false; return false;
} }
# ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* MDD is big-endian, its values need to be switched on little-endian systems. */
BLI_endian_switch_float_array(vertexCos[0], mdd_head.verts_tot * 3); BLI_endian_switch_float_array(vertexCos[0], mdd_head.verts_tot * 3);
# endif
#endif #endif
} }
else { else {
@ -194,11 +193,11 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
float tvec[3]; float tvec[3];
verts_read_num += fread(tvec, sizeof(float[3]), 1, fp); verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
/* MDD is big-endian, its values need to be switched on little-endian systems. */
BLI_endian_switch_float(tvec + 0); BLI_endian_switch_float(tvec + 0);
BLI_endian_switch_float(tvec + 1); BLI_endian_switch_float(tvec + 1);
BLI_endian_switch_float(tvec + 2); BLI_endian_switch_float(tvec + 2);
#endif
vco[0] = (vco[0] * ifactor) + (tvec[0] * factor); vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
vco[1] = (vco[1] * ifactor) + (tvec[1] * factor); vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);

View File

@ -14,9 +14,6 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#ifdef __BIG_ENDIAN__
# include "BLI_endian_switch.h"
#endif
#ifdef WIN32 #ifdef WIN32
# include "BLI_winstuff.h" # include "BLI_winstuff.h"
@ -52,10 +49,9 @@ static bool meshcache_read_pc2_head(FILE *fp,
return false; return false;
} }
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
BLI_endian_switch_int32_array(&pc2_head->file_version, /* The pc2_head->file_version and following values would need to be switched on big-endian
(sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int)); * systems. */
#endif
if (pc2_head->verts_tot != verts_tot) { if (pc2_head->verts_tot != verts_tot) {
*r_err_str = RPT_("Vertex count mismatch"); *r_err_str = RPT_("Vertex count mismatch");
@ -150,11 +146,8 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) { for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
verts_read_num += fread(vco, sizeof(float[3]), 1, fp); verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
BLI_endian_switch_float(vco + 0); /* The `vco` values would need to be switched on big-endian systems. */
BLI_endian_switch_float(vco + 1);
BLI_endian_switch_float(vco + 2);
#endif /* __BIG_ENDIAN__ */
} }
} }
else { else {
@ -165,11 +158,8 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
float tvec[3]; float tvec[3];
verts_read_num += fread(tvec, sizeof(float[3]), 1, fp); verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
#ifdef __BIG_ENDIAN__ /* NOTE: this is endianness-sensitive. */
BLI_endian_switch_float(tvec + 0); /* The `tvec` values would need to be switched on big-endian systems. */
BLI_endian_switch_float(tvec + 1);
BLI_endian_switch_float(tvec + 2);
#endif /* __BIG_ENDIAN__ */
vco[0] = (vco[0] * ifactor) + (tvec[0] * factor); vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
vco[1] = (vco[1] * ifactor) + (tvec[1] * factor); vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);

View File

@ -39,11 +39,8 @@ short euler_order_from_string(const char *str, const char *error_prefix)
{ {
if (str[0] && str[1] && str[2] && str[3] == '\0') { if (str[0] && str[1] && str[2] && str[3] == '\0') {
#ifdef __LITTLE_ENDIAN__ /* NOTE: this is endianness-sensitive. */
# define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16)) #define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16))
#else
# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
#endif
switch (*((const PY_INT32_T *)str)) { switch (*((const PY_INT32_T *)str)) {
case MAKE_ID3('X', 'Y', 'Z'): case MAKE_ID3('X', 'Y', 'Z'):

View File

@ -28,6 +28,7 @@
#include "DNA_genfile.h" #include "DNA_genfile.h"
#include "BLI_endian_defines.h"
#include "BLI_fftw.hh" #include "BLI_fftw.hh"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_system.h" #include "BLI_system.h"
@ -98,6 +99,8 @@
#include "creator_intern.h" /* Own include. */ #include "creator_intern.h" /* Own include. */
BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name Local Defines /** \name Local Defines
* \{ */ * \{ */

View File

@ -31,30 +31,205 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
# Each file in this list should either be the source of a bug report, # Each file in this list should either be the source of a bug report,
# or removed from tests repo. # or removed from tests repo.
self.excluded_paths = { self.excluded_paths = {
# tests/modifier_stack/explode_modifier.blend # modifier_stack/explode_modifier.blend
# BLI_assert failed: source/blender/blenlib/BLI_ordered_edge.hh:41, operator==(), at 'e1.v_low < e1.v_high' # BLI_assert failed: source/blender/blenlib/BLI_ordered_edge.hh:41, operator==(), at 'e1.v_low < e1.v_high'
"explode_modifier.blend", "explode_modifier.blend",
# tests/depsgraph/deg_anim_camera_dof_driving_material.blend # depsgraph/deg_anim_camera_dof_driving_material.blend
# ERROR (bke.fcurve): # ERROR (bke.fcurve):
# source/blender/blenkernel/intern/fcurve_driver.cc:188 dtar_get_prop_val: # source/blender/blenkernel/intern/fcurve_driver.cc:188 dtar_get_prop_val:
# Driver Evaluation Error: cannot resolve target for OBCamera -> # Driver Evaluation Error: cannot resolve target for OBCamera ->
# data.dof_distance # data.dof_distance
"deg_anim_camera_dof_driving_material.blend", "deg_anim_camera_dof_driving_material.blend",
# tests/depsgraph/deg_driver_shapekey_same_datablock.blend # depsgraph/deg_driver_shapekey_same_datablock.blend
# Error: Not freed memory blocks: 4, total unfreed memory 0.000427 MB # Error: Not freed memory blocks: 4, total unfreed memory 0.000427 MB
"deg_driver_shapekey_same_datablock.blend", "deg_driver_shapekey_same_datablock.blend",
# tests/physics/fluidsim.blend # physics/fluidsim.blend
# Error: Not freed memory blocks: 3, total unfreed memory 0.003548 MB # Error: Not freed memory blocks: 3, total unfreed memory 0.003548 MB
"fluidsim.blend", "fluidsim.blend",
# tests/opengl/ram_glsl.blend # opengl/ram_glsl.blend
# Error: Not freed memory blocks: 4, total unfreed memory 0.000427 MB # Error: Not freed memory blocks: 4, total unfreed memory 0.000427 MB
"ram_glsl.blend", "ram_glsl.blend",
} }
# Some files are expected to be invalid.
# This mapping stores filenames as keys, and expected error message as value.
self.invalid_paths = {
# animation/driver-object-eyes.blend
# File generated from a big endian build of Blender.
"driver-object-eyes.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# modeling/faceselectmode.blend
# File generated from a big endian build of Blender.
"faceselectmode.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# modeling/weight-paint_test.blend
# File generated from a big endian build of Blender.
"weight-paint_test.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/1.62/glass.blend
# File generated from a big endian build of Blender.
"glass.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/1.62/room.blend
# File generated from a big endian build of Blender.
"room.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/1.69/s-mesh.blend
# File generated from a big endian build of Blender.
"s-mesh.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/1.70/escher.blend
# File generated from a big endian build of Blender.
"escher.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/1.98/egypt.blend
# File generated from a big endian build of Blender.
"egypt.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.25/FroggyPacked.blend
# File generated from a big endian build of Blender.
"FroggyPacked.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.30/CtrlObject.blend
# File generated from a big endian build of Blender.
"CtrlObject.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.30/demofile.blend
# File generated from a big endian build of Blender.
"demofile.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.30/dolphin.blend
# File generated from a big endian build of Blender.
"dolphin.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.30/mball.blend
# File generated from a big endian build of Blender.
"mball.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.30/motor9.blend
# File generated from a big endian build of Blender.
"motor9.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.30/relative.blend
# File generated from a big endian build of Blender.
"relative.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/Raptor.blend
# File generated from a big endian build of Blender.
"Raptor.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/allselect.blend
# File generated from a big endian build of Blender.
"allselect.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/arealight.blend
# File generated from a big endian build of Blender.
"arealight.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/hairball.blend
# File generated from a big endian build of Blender.
"hairball.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/luxo.blend
# File generated from a big endian build of Blender.
"luxo.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/monkey_cornelius.blend
# File generated from a big endian build of Blender.
"monkey_cornelius.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/refract_monkey.blend
# File generated from a big endian build of Blender.
"refract_monkey.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.31/robo.blend
# File generated from a big endian build of Blender.
"robo.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.34/flippedmatrixes.blend
# File generated from a big endian build of Blender.
"flippedmatrixes.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.34/lostride.blend
# File generated from a big endian build of Blender.
"lostride.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.34/tapercurve.blend
# File generated from a big endian build of Blender.
"tapercurve.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.36/pathdist.blend
# File generated from a big endian build of Blender.
"pathdist.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
# io_tests/blend_big_endian/2.76/bird_sintel.blend
# File generated from a big endian build of Blender.
"bird_sintel.blend": (
(OSError, RuntimeError),
"created by a Big Endian version of Blender, support for these files has been removed in Blender 5.0"
),
}
# Directories to exclude relative to `./tests/files/`. # Directories to exclude relative to `./tests/files/`.
self.excluded_dirs = () self.excluded_dirs = ()
@ -102,6 +277,18 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
return True return True
return False return False
def invalid_path_exception_process(self, bfp, exception):
expected_failure = self.invalid_paths.get(os.path.basename(bfp), None)
if not expected_failure:
raise exception
# Check expected exception type(s).
if not isinstance(exception, expected_failure[0]):
raise exception
# Check expected exception (partial) message.
if expected_failure[1] not in str(exception):
raise exception
print(f"\tExpected failure: '{exception}'", flush=True)
def test_open(self): def test_open(self):
for bfp in self.blendfile_paths: for bfp in self.blendfile_paths:
if self.skip_path_check(bfp): if self.skip_path_check(bfp):
@ -109,7 +296,10 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
if not self.args.is_quiet: if not self.args.is_quiet:
print(f"Trying to open {bfp}", flush=True) print(f"Trying to open {bfp}", flush=True)
bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
bpy.ops.wm.open_mainfile(filepath=bfp, load_ui=False) try:
bpy.ops.wm.open_mainfile(filepath=bfp, load_ui=False)
except BaseException as e:
self.invalid_path_exception_process(bfp, e)
def link_append(self, do_link): def link_append(self, do_link):
operation_name = "link" if do_link else "append" operation_name = "link" if do_link else "append"
@ -117,15 +307,18 @@ class TestBlendFileOpenAllTestFiles(TestHelper):
if self.skip_path_check(bfp): if self.skip_path_check(bfp):
continue continue
bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
with bpy.data.libraries.load(bfp, link=do_link) as (lib_in, lib_out): try:
if len(lib_in.collections): with bpy.data.libraries.load(bfp, link=do_link) as (lib_in, lib_out):
if not self.args.is_quiet: if len(lib_in.collections):
print(f"Trying to {operation_name} {bfp}/Collection/{lib_in.collections[0]}", flush=True) if not self.args.is_quiet:
lib_out.collections.append(lib_in.collections[0]) print(f"Trying to {operation_name} {bfp}/Collection/{lib_in.collections[0]}", flush=True)
elif len(lib_in.objects): lib_out.collections.append(lib_in.collections[0])
if not self.args.is_quiet: elif len(lib_in.objects):
print(f"Trying to {operation_name} {bfp}/Object/{lib_in.objects[0]}", flush=True) if not self.args.is_quiet:
lib_out.objects.append(lib_in.objects[0]) print(f"Trying to {operation_name} {bfp}/Object/{lib_in.objects[0]}", flush=True)
lib_out.objects.append(lib_in.objects[0])
except BaseException as e:
self.invalid_path_exception_process(bfp, e)
def test_link(self): def test_link(self):
self.link_append(do_link=True) self.link_append(do_link=True)