Add Chromium-only Blender WebEngine parity work
This commit is contained in:
313
blender-5.2.0/intern/cycles/blender/id_map.h
Normal file
313
blender-5.2.0/intern/cycles/blender/id_map.h
Normal file
@@ -0,0 +1,313 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/scene.h"
|
||||
|
||||
#include "util/map.h"
|
||||
#include "util/set.h"
|
||||
|
||||
namespace blender {
|
||||
struct ID;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* ID Map
|
||||
*
|
||||
* Utility class to map between Blender datablocks and Cycles data structures,
|
||||
* and keep track of recalc tags from the dependency graph. */
|
||||
|
||||
template<typename K, typename T, typename Flags = uint> class id_map {
|
||||
public:
|
||||
id_map(Scene *scene_) : scene(scene_) {}
|
||||
|
||||
~id_map()
|
||||
{
|
||||
set<T *> nodes;
|
||||
|
||||
typename map<K, T *>::iterator jt;
|
||||
for (jt = b_map.begin(); jt != b_map.end(); jt++) {
|
||||
nodes.insert(jt->second);
|
||||
}
|
||||
|
||||
scene->delete_nodes(nodes);
|
||||
}
|
||||
|
||||
T *find(const K &key)
|
||||
{
|
||||
if (b_map.find(key) != b_map.end()) {
|
||||
T *data = b_map[key];
|
||||
return data;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void set_recalc(void *id_ptr)
|
||||
{
|
||||
b_recalc.insert(id_ptr);
|
||||
}
|
||||
|
||||
bool check_recalc(const blender::ID *id)
|
||||
{
|
||||
return id && b_recalc.contains(id);
|
||||
}
|
||||
|
||||
bool has_recalc()
|
||||
{
|
||||
return !(b_recalc.empty());
|
||||
}
|
||||
|
||||
void pre_sync()
|
||||
{
|
||||
used_set.clear();
|
||||
}
|
||||
|
||||
/* Add new data. */
|
||||
void add(const K &key, T *data)
|
||||
{
|
||||
assert(find(key) == nullptr);
|
||||
b_map[key] = data;
|
||||
used(data);
|
||||
}
|
||||
|
||||
/* Update existing data. */
|
||||
bool update(T *data, const blender::ID *id)
|
||||
{
|
||||
return update(data, id, id);
|
||||
}
|
||||
bool update(T *data, const blender::ID *id, const blender::ID *parent)
|
||||
{
|
||||
bool recalc = (b_recalc.contains(id));
|
||||
if (parent && parent != id) {
|
||||
recalc = recalc || (b_recalc.contains(parent));
|
||||
}
|
||||
used(data);
|
||||
return recalc;
|
||||
}
|
||||
|
||||
/* Combined add and update as needed. */
|
||||
bool add_or_update(T **r_data, const blender::ID *id)
|
||||
{
|
||||
return add_or_update(r_data, id, id, id);
|
||||
}
|
||||
bool add_or_update(T **r_data, const blender::ID *id, const K &key)
|
||||
{
|
||||
return add_or_update(r_data, id, id, key);
|
||||
}
|
||||
bool add_or_update(T **r_data, const blender::ID *id, const blender::ID *parent, const K &key)
|
||||
{
|
||||
T *data = find(key);
|
||||
bool recalc;
|
||||
|
||||
if (!data) {
|
||||
/* Add data if it didn't exist yet. */
|
||||
data = scene->create_node<T>();
|
||||
add(key, data);
|
||||
recalc = true;
|
||||
}
|
||||
else {
|
||||
/* check if updated needed. */
|
||||
recalc = update(data, id, parent);
|
||||
}
|
||||
|
||||
*r_data = data;
|
||||
return recalc;
|
||||
}
|
||||
|
||||
/* Combined add or update for convenience. */
|
||||
|
||||
bool is_used(const K &key)
|
||||
{
|
||||
T *data = find(key);
|
||||
return (data) ? used_set.find(data) != used_set.end() : false;
|
||||
}
|
||||
|
||||
void used(T *data)
|
||||
{
|
||||
/* tag data as still in use */
|
||||
used_set.insert(data);
|
||||
}
|
||||
|
||||
void set_default(T *data)
|
||||
{
|
||||
b_map[nullptr] = data;
|
||||
}
|
||||
|
||||
void post_sync(bool do_delete = true)
|
||||
{
|
||||
map<K, T *> new_map;
|
||||
set<T *> nodes_to_delete;
|
||||
using TMapPair = pair<const K, T *>;
|
||||
typename map<K, T *>::iterator jt;
|
||||
|
||||
for (jt = b_map.begin(); jt != b_map.end(); jt++) {
|
||||
TMapPair &pair = *jt;
|
||||
|
||||
if (do_delete && used_set.find(pair.second) == used_set.end()) {
|
||||
flags.erase(pair.second);
|
||||
nodes_to_delete.insert(pair.second);
|
||||
}
|
||||
else {
|
||||
new_map[pair.first] = pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nodes_to_delete.empty()) {
|
||||
scene->delete_nodes(nodes_to_delete);
|
||||
}
|
||||
|
||||
used_set.clear();
|
||||
b_recalc.clear();
|
||||
b_map = new_map;
|
||||
}
|
||||
|
||||
const map<K, T *> &key_to_scene_data()
|
||||
{
|
||||
return b_map;
|
||||
}
|
||||
|
||||
bool test_flag(T *data, Flags val)
|
||||
{
|
||||
typename map<T *, uint>::iterator it = flags.find(data);
|
||||
return it != flags.end() && (it->second & (1 << val)) != 0;
|
||||
}
|
||||
|
||||
void set_flag(T *data, Flags val)
|
||||
{
|
||||
flags[data] |= (1 << val);
|
||||
}
|
||||
|
||||
void clear_flag(T *data, Flags val)
|
||||
{
|
||||
typename map<T *, uint>::iterator it = flags.find(data);
|
||||
if (it != flags.end()) {
|
||||
it->second &= ~(1 << val);
|
||||
|
||||
if (it->second == 0) {
|
||||
flags.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
map<K, T *> b_map;
|
||||
set<T *> used_set;
|
||||
map<T *, uint> flags;
|
||||
set<const void *> b_recalc;
|
||||
Scene *scene;
|
||||
};
|
||||
|
||||
/* Object Key
|
||||
*
|
||||
* To uniquely identify instances, we use the parent, object and persistent instance ID.
|
||||
* We also export separate object for a mesh and its particle hair. */
|
||||
|
||||
enum { OBJECT_PERSISTENT_ID_SIZE = 8 /* MAX_DUPLI_RECUR in Blender. */ };
|
||||
|
||||
struct ObjectKey {
|
||||
void *parent;
|
||||
int id[OBJECT_PERSISTENT_ID_SIZE];
|
||||
void *ob;
|
||||
bool use_particle_hair;
|
||||
|
||||
ObjectKey(void *parent_,
|
||||
const int id_[OBJECT_PERSISTENT_ID_SIZE],
|
||||
void *ob_,
|
||||
bool use_particle_hair_)
|
||||
: parent(parent_), ob(ob_), use_particle_hair(use_particle_hair_)
|
||||
{
|
||||
if (id_) {
|
||||
memcpy(id, id_, sizeof(id));
|
||||
}
|
||||
else {
|
||||
memset(id, 0, sizeof(id));
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const ObjectKey &k) const
|
||||
{
|
||||
if (ob < k.ob) {
|
||||
return true;
|
||||
}
|
||||
if (ob == k.ob) {
|
||||
if (parent < k.parent) {
|
||||
return true;
|
||||
}
|
||||
if (parent == k.parent) {
|
||||
if (use_particle_hair < k.use_particle_hair) {
|
||||
return true;
|
||||
}
|
||||
if (use_particle_hair == k.use_particle_hair) {
|
||||
return memcmp(id, k.id, sizeof(id)) < 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Geometry Key
|
||||
*
|
||||
* We export separate geometry for a mesh and its particle hair, so key needs to
|
||||
* distinguish between them. */
|
||||
|
||||
struct GeometryKey {
|
||||
void *id;
|
||||
Geometry::Type geometry_type;
|
||||
|
||||
GeometryKey(void *id, Geometry::Type geometry_type) : id(id), geometry_type(geometry_type) {}
|
||||
|
||||
bool operator<(const GeometryKey &k) const
|
||||
{
|
||||
if (id < k.id) {
|
||||
return true;
|
||||
}
|
||||
if (id == k.id) {
|
||||
if (geometry_type < k.geometry_type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Particle System Key */
|
||||
|
||||
struct ParticleSystemKey {
|
||||
void *ob;
|
||||
int id[OBJECT_PERSISTENT_ID_SIZE];
|
||||
|
||||
ParticleSystemKey(void *ob_, const int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
|
||||
{
|
||||
if (id_) {
|
||||
memcpy(id, id_, sizeof(id));
|
||||
}
|
||||
else {
|
||||
memset(id, 0, sizeof(id));
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const ParticleSystemKey &k) const
|
||||
{
|
||||
/* first id is particle index, we don't compare that */
|
||||
if (ob < k.ob) {
|
||||
return true;
|
||||
}
|
||||
if (ob == k.ob) {
|
||||
return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
Reference in New Issue
Block a user