vtkPVDataDeliveryManagerInternals.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
2 // SPDX-License-Identifier: BSD-3-Clause
3 #ifndef vtkPVDataDeliveryManagerInternals_h
4 #define vtkPVDataDeliveryManagerInternals_h
5 #ifndef __WRAP__
6 
7 #include "vtkDataObject.h" // for vtkDataObject
8 #include "vtkInformation.h" // for vtkInformation
9 #include "vtkNew.h" // for vtkNew
11 #include "vtkPVDataRepresentation.h" // for vtkPVDataRepresentation
12 #include "vtkPVTrivialProducer.h" // for vtkPVTrivialProducer
13 #include "vtkSmartPointer.h" // for vtkSmartPointer
14 #include "vtkWeakPointer.h" // for vtkWeakPointer
15 
16 #include <cassert> // for assert
17 #include <map> // for std::map
18 #include <numeric> // for std::accumulate
19 #include <utility> // for std::pair
20 
22 {
23  friend class vtkItem;
24  std::map<int, vtkSmartPointer<vtkDataObject>> EmptyDataObjectTypes;
25 
26  // This helps us avoid creating new instances of various data object types to use as
27  // empty datasets. Instead, we build a map and keep reusing objects.
28  vtkDataObject* GetEmptyDataObject(vtkDataObject* ref)
29  {
30  if (ref)
31  {
32  auto iter = this->EmptyDataObjectTypes.find(ref->GetDataObjectType());
33  if (iter != this->EmptyDataObjectTypes.end())
34  {
35  return iter->second;
36  }
37  else
38  {
40  clone.TakeReference(ref->NewInstance());
41  this->EmptyDataObjectTypes[ref->GetDataObjectType()] = clone;
42  return clone;
43  }
44  }
45  return nullptr;
46  }
47 
48 public:
50  {
51  // Data object produced by the representation.
53 
54  // Data object available after delivery to the "rendering" node.
55  std::map<int, vtkSmartPointer<vtkDataObject>> DeliveredDataObjects;
56 
57  // Some useful meta-data.
60 
61  // Arbitrary meta-data container.
63  };
64 
65  class vtkItem
66  {
68 
69  // Store of data generated by the representation for rendering.
70  // The store keeps data at various stages of the pipeline along with
71  // relevant cache, as appropriate.
72  std::map<double, vtkRepresentedData> Data;
73 
75 
76  public:
77  vtkItem() = default;
78 
79  void ClearCache() { this->Data.clear(); }
80 
81  void SetDataObject(vtkDataObject* data, vtkInternals* helper, double cacheKey)
82  {
83  auto& store = this->Data[cacheKey];
84  if (data)
85  {
86  store.DataObject.TakeReference(data->NewInstance());
87  store.DataObject->ShallowCopy(data);
88  }
89  else
90  {
91  store.DataObject = nullptr;
92  }
93 
94  store.DeliveredDataObjects.clear();
95  store.ActualMemorySize = data ? data->GetActualMemorySize() : 0;
96  // This method gets called when data is entirely changed. That means that any
97  // data we may have delivered or redistributed would also be obsolete.
98  // Hence we reset the `Producer` as well. This avoids #2160.
99 
100  // explanation for using a clone: typically, the Producer is connected by the
101  // representation to a rendering pipeline e.g. the mapper. As that could be the
102  // case, we need to ensure the producer's input is cleaned too. Setting simply nullptr
103  // could confuse the mapper and hence we setup a data object of the same type as the data.
104  // we could simply set the data too, but that can lead to other confusion as the mapper should
105  // never directly see the representation's data.
106  this->Producer->SetOutput(helper->GetEmptyDataObject(data));
107 
108  vtkTimeStamp ts;
109  ts.Modified();
110  store.TimeStamp = ts;
111  this->TimeStamp = ts;
112  }
113 
114  void SetActualMemorySize(unsigned long size, double cacheKey)
115  {
116  auto& store = this->Data[cacheKey];
117  store.ActualMemorySize = size;
118  }
119 
120  unsigned long GetActualMemorySize(double cacheKey) const
121  {
122  auto iter = this->Data.find(cacheKey);
123  return iter != this->Data.end() ? iter->second.ActualMemorySize : 0;
124  }
125 
126  vtkDataObject* GetDeliveredDataObject(int dataKey, double cacheKey) const
127  {
128  try
129  {
130  const auto& store = this->Data.at(cacheKey);
131  return store.DeliveredDataObjects.at(dataKey);
132  }
133  catch (std::out_of_range&)
134  {
135  return nullptr;
136  }
137  }
138 
139  void SetDeliveredDataObject(int dataKey, double cacheKey, vtkDataObject* data)
140  {
141  auto& store = this->Data[cacheKey];
142  store.DeliveredDataObjects[dataKey] = data;
143  }
144 
145  vtkPVTrivialProducer* GetProducer(int dataKey, double cacheKey)
146  {
147  vtkDataObject* prev = this->Producer->GetOutputDataObject(0);
148  vtkDataObject* cur = this->GetDeliveredDataObject(dataKey, cacheKey);
149  this->Producer->SetOutput(cur);
150  if (cur != prev && cur != nullptr)
151  {
152  // this is only needed to overcome a bug in the mapper where they are
153  // using input's mtime incorrectly.
154  cur->Modified();
155  }
156  return this->Producer.GetPointer();
157  }
158 
159  vtkDataObject* GetDataObject(double cacheKey) const
160  {
161  auto iter = this->Data.find(cacheKey);
162  return iter != this->Data.end() ? iter->second.DataObject.GetPointer() : nullptr;
163  }
164 
165  vtkMTimeType GetTimeStamp(double cacheKey) const
166  {
167  auto iter = this->Data.find(cacheKey);
168  return iter != this->Data.end() ? iter->second.TimeStamp : vtkMTimeType{ 0 };
169  }
170 
172  {
173  auto& store = this->Data[cacheKey];
174  if (store.Information == nullptr)
175  {
176  store.Information = vtkSmartPointer<vtkInformation>::New();
177  }
178  return store.Information;
179  }
180 
181  vtkMTimeType GetTimeStamp() const { return this->TimeStamp; }
182  vtkMTimeType GetDeliveryTimeStamp(int dataKey, double cacheKey) const
183  {
184  if (auto dobj = this->GetDeliveredDataObject(dataKey, cacheKey))
185  {
186  return dobj->GetMTime();
187  }
188  return vtkMTimeType{ 0 };
189  }
190  };
191 
192  // First is repr unique id, second is the input port.
193  typedef std::pair<unsigned int, int> ReprPortType;
194  typedef std::map<ReprPortType, std::pair<vtkItem, vtkItem>> ItemsMapType;
195 
196  // Keep track of representation and its uid.
197  typedef std::map<unsigned int, vtkWeakPointer<vtkPVDataRepresentation>> RepresentationsMapType;
198 
199  vtkItem* GetItem(unsigned int index, bool use_second, int port, bool create_if_needed = false)
200  {
201  ReprPortType key(index, port);
202  ItemsMapType::iterator items = this->ItemsMap.find(key);
203  if (items != this->ItemsMap.end())
204  {
205  return use_second ? &(items->second.second) : &(items->second.first);
206  }
207  else if (create_if_needed)
208  {
209  std::pair<vtkItem, vtkItem>& itemsPair = this->ItemsMap[key];
210  return use_second ? &(itemsPair.second) : &(itemsPair.first);
211  }
212  return nullptr;
213  }
214 
216  vtkPVDataRepresentation* repr, bool use_second, int port, bool create_if_needed = false)
217  {
218  return this->GetItem(repr->GetUniqueIdentifier(), use_second, port, create_if_needed);
219  }
220 
222  {
223  const auto id = repr->GetUniqueIdentifier();
224  return std::accumulate(this->ItemsMap.begin(), this->ItemsMap.end(), 0,
225  [&id](int sum, const ItemsMapType::value_type& item_pair) {
226  return sum + (item_pair.first.first == id ? 1 : 0);
227  });
228  }
229 
230  unsigned long GetVisibleDataSize(bool use_second_if_available, vtkPVDataDeliveryManager* dmgr)
231  {
232  unsigned long size = 0;
233  ItemsMapType::iterator iter;
234  for (iter = this->ItemsMap.begin(); iter != this->ItemsMap.end(); ++iter)
235  {
236  const ReprPortType& key = iter->first;
237  if (!this->IsRepresentationVisible(key.first))
238  {
239  // skip hidden representations.
240  continue;
241  }
242 
243  auto repr = this->RepresentationsMap[key.first];
244  assert(repr != nullptr);
245  const double cacheKey = dmgr->GetCacheKey(repr);
246 
247  if (use_second_if_available && iter->second.second.GetDataObject(cacheKey))
248  {
249  size += iter->second.second.GetActualMemorySize(cacheKey);
250  }
251  else
252  {
253  size += iter->second.first.GetActualMemorySize(cacheKey);
254  }
255  }
256  return size;
257  }
258 
259  bool IsRepresentationVisible(unsigned int id) const
260  {
261  RepresentationsMapType::const_iterator riter = this->RepresentationsMap.find(id);
262  return (riter != this->RepresentationsMap.end() && riter->second.GetPointer() != nullptr &&
263  riter->second->GetVisibility());
264  }
265 
267  void ClearCache(unsigned int id)
268  {
269  for (auto& ipair : this->ItemsMap)
270  {
271  if (ipair.first.first == id)
272  {
273  ipair.second.first.ClearCache();
274  ipair.second.second.ClearCache();
275  }
276  }
277  }
278 
279  ItemsMapType ItemsMap;
280  RepresentationsMapType RepresentationsMap;
281 };
282 
283 #endif // __WRAP__
284 #endif
285 // VTK-HeaderTest-Exclude: vtkPVDataDeliveryManagerInternals.h
manager for data-delivery.
void SetDataObject(vtkDataObject *data, vtkInternals *helper, double cacheKey)
std::map< ReprPortType, std::pair< vtkItem, vtkItem > > ItemsMapType
void SetOutput(vtkDataObject *output) override
Set the data object that is "produced" by this producer.
vtkItem * GetItem(vtkPVDataRepresentation *repr, bool use_second, int port, bool create_if_needed=false)
unsigned long GetVisibleDataSize(bool use_second_if_available, vtkPVDataDeliveryManager *dmgr)
vtkPVDataRepresentation adds some ParaView specific API to data representations.
vtkPVTrivialProducer * GetProducer(int dataKey, double cacheKey)
void Modified()
double GetCacheKey(vtkPVDataRepresentation *repr) const
void SetActualMemorySize(unsigned long size, double cacheKey)
vtkDataObject * GetOutputDataObject(int port)
static vtkSmartPointer< T > New()
vtkTypeUInt64 vtkMTimeType
unsigned int GetUniqueIdentifier()
Return 0 if the Initialize() method was not called otherwise a unique ID that will be shared across t...
vtkDataObject * NewInstance() const
specialized subclass of vtkTrivialProducer that preserves the information about the whole extent of t...
std::map< unsigned int, vtkWeakPointer< vtkPVDataRepresentation > > RepresentationsMapType
void SetDeliveredDataObject(int dataKey, double cacheKey, vtkDataObject *data)
virtual void Modified()
size
virtual unsigned long GetActualMemorySize()
void TakeReference(vtkDataObject *t)
T * GetPointer() const
vtkDataObject * GetDeliveredDataObject(int dataKey, double cacheKey) const
virtual int GetDataObjectType()
vtkItem * GetItem(unsigned int index, bool use_second, int port, bool create_if_needed=false)
key
vtkMTimeType GetDeliveryTimeStamp(int dataKey, double cacheKey) const
std::map< int, vtkSmartPointer< vtkDataObject > > DeliveredDataObjects