vsg  1.1.0
VulkanSceneGraph library
Array2D.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2018 Robert Osfield
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 </editor-fold> */
14 
15 #include <vsg/core/Data.h>
16 
17 #include <vsg/maths/mat4.h>
18 #include <vsg/maths/vec2.h>
19 #include <vsg/maths/vec3.h>
20 #include <vsg/maths/vec4.h>
21 
22 #include <vsg/io/Input.h>
23 #include <vsg/io/Output.h>
24 
25 #define VSG_array2D(N, T) \
26  using N = Array2D<T>; \
27  template<> \
28  constexpr const char* type_name<N>() noexcept { return "vsg::" #N; }
29 
30 namespace vsg
31 {
32 
33  template<typename T>
34  class Array2D : public Data
35  {
36  public:
37  using value_type = T;
40 
41  Array2D() :
42  _data(nullptr),
43  _width(0),
44  _height(0) {}
45 
46  Array2D(const Array2D& rhs) :
47  Data(rhs.properties, sizeof(value_type)),
48  _data(nullptr),
49  _width(rhs._width),
50  _height(rhs._height)
51  {
52  if (_width != 0 && _height != 0)
53  {
54  _data = _allocate(_width * _height);
55  auto dest_v = _data;
56  for (auto& v : rhs) *(dest_v++) = v;
57  }
58  dirty();
59  }
60 
61  Array2D(uint32_t width, uint32_t height, Properties in_properties = {}) :
62  Data(in_properties, sizeof(value_type)),
63  _data(_allocate(width * height)),
64  _width(width),
65  _height(height) { dirty(); }
66 
67  Array2D(uint32_t width, uint32_t height, value_type* data, Properties in_properties = {}) :
68  Data(in_properties, sizeof(value_type)),
69  _data(data),
70  _width(width),
71  _height(height) { dirty(); }
72 
73  Array2D(uint32_t width, uint32_t height, const value_type& value, Properties in_properties = {}) :
74  Data(in_properties, sizeof(value_type)),
75  _data(_allocate(width * height)),
76  _width(width),
77  _height(height)
78  {
79  for (auto& v : *this) v = value;
80  dirty();
81  }
82 
83  Array2D(ref_ptr<Data> data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, Properties in_properties = {}) :
84  Data(),
85  _data(nullptr),
86  _width(0),
87  _height(0)
88  {
89  assign(data, offset, stride, width, height, in_properties);
90  }
91 
92  template<typename... Args>
93  static ref_ptr<Array2D> create(Args&&... args)
94  {
95  return ref_ptr<Array2D>(new Array2D(args...));
96  }
97 
98  ref_ptr<Data> clone() const override
99  {
100  return ref_ptr<Array2D>(new Array2D(*this));
101  }
102 
103  size_t sizeofObject() const noexcept override { return sizeof(Array2D); }
104  const char* className() const noexcept override { return type_name<Array2D>(); }
105  const std::type_info& type_info() const noexcept override { return typeid(*this); }
106  bool is_compatible(const std::type_info& type) const noexcept override { return typeid(Array2D) == type || Data::is_compatible(type); }
107 
108  // implementation provided by Visitor.h
109  void accept(Visitor& visitor) override;
110  void accept(ConstVisitor& visitor) const override;
111 
112  void read(Input& input) override
113  {
114  size_t original_size = size();
115 
116  Data::read(input);
117 
118  uint32_t w = input.readValue<uint32_t>("width");
119  uint32_t h = input.readValue<uint32_t>("height");
120 
121  if (auto data_storage = input.readObject<Data>("storage"))
122  {
123  uint32_t offset = input.readValue<uint32_t>("offset");
124  assign(data_storage, offset, properties.stride, w, h, properties);
125  return;
126  }
127 
128  if (input.matchPropertyName("data"))
129  {
130  size_t new_size = computeValueCountIncludingMipmaps(w, h, 1, properties.maxNumMipmaps);
131 
132  if (_data) // if data exists already may be able to reuse it
133  {
134  if (original_size != new_size) // if existing data is a different size delete old, and create new
135  {
136  _delete();
137  _data = _allocate(new_size);
138  }
139  }
140  else // allocate space for data
141  {
142  _data = _allocate(new_size);
143  }
144 
145  properties.stride = sizeof(value_type);
146  _width = w;
147  _height = h;
148  _storage = nullptr;
149 
150  if (_data) input.read(new_size, _data);
151 
152  dirty();
153  }
154  }
155 
156  void write(Output& output) const override
157  {
158  Data::write(output);
159 
160  output.writeValue<uint32_t>("width", _width);
161  output.writeValue<uint32_t>("height", _height);
162 
163  output.writeObject("storage", _storage);
164  if (_storage)
165  {
166  auto offset = (reinterpret_cast<uintptr_t>(_data) - reinterpret_cast<uintptr_t>(_storage->dataPointer()));
167  output.writeValue<uint32_t>("offset", offset);
168  return;
169  }
170 
171  output.writePropertyName("data");
172  output.write(valueCount(), _data);
173  output.writeEndOfLine();
174  }
175 
176  size_t size() const { return (properties.maxNumMipmaps <= 1) ? static_cast<size_t>(_width * _height) : computeValueCountIncludingMipmaps(_width, _height, 1, properties.maxNumMipmaps); }
177 
178  bool available() const { return _data != nullptr; }
179  bool empty() const { return _data == nullptr; }
180 
181  void clear()
182  {
183  _delete();
184 
185  _width = 0;
186  _height = 0;
187  _data = nullptr;
188  _storage = nullptr;
189  }
190 
191  Array2D& operator=(const Array2D& rhs)
192  {
193  if (&rhs == this) return *this;
194 
195  clear();
196 
197  properties = rhs.properties;
198  _width = rhs._width;
199  _height = rhs._height;
200 
201  if (_width != 0 && _height != 0)
202  {
203  _data = _allocate(_width * _height);
204  auto dest_v = _data;
205  for (auto& v : rhs) *(dest_v++) = v;
206  }
207 
208  dirty();
209 
210  return *this;
211  }
212 
213  void assign(uint32_t width, uint32_t height, value_type* data, Properties in_properties = {})
214  {
215  _delete();
216 
217  properties = in_properties;
218  properties.stride = sizeof(value_type);
219  _width = width;
220  _height = height;
221  _data = data;
222  _storage = nullptr;
223 
224  dirty();
225  }
226 
227  void assign(ref_ptr<Data> storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, Properties in_properties = {})
228  {
229  _delete();
230 
231  _storage = storage;
232  properties = in_properties;
233  properties.stride = stride;
234  if (_storage && _storage->dataPointer())
235  {
236  _data = reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_storage->dataPointer()) + offset);
237  _width = width;
238  _height = height;
239  }
240  else
241  {
242  _data = nullptr;
243  _width = 0;
244  _height = 0;
245  }
246 
247  dirty();
248  }
249 
250  // release the data so that ownership can be passed on, the local data pointer and size is set to 0 so that destruction of Array will not result in the data being deleted.
251  // if the data is stored in a separate vsg::Data object then return nullptr and do not attempt to release data.
252  void* dataRelease() override
253  {
254  if (!_storage)
255  {
256  void* tmp = _data;
257  _data = nullptr;
258  _width = 0;
259  _height = 0;
260  return tmp;
261  }
262  else
263  {
264  return nullptr;
265  }
266  }
267 
268  size_t valueSize() const override { return sizeof(value_type); }
269  size_t valueCount() const override { return size(); }
270 
271  bool dataAvailable() const override { return available(); }
272  size_t dataSize() const override { return size() * properties.stride; }
273 
274  void* dataPointer() override { return _data; }
275  const void* dataPointer() const override { return _data; }
276 
277  void* dataPointer(size_t i) override { return data(i); }
278  const void* dataPointer(size_t i) const override { return data(i); }
279 
280  uint32_t dimensions() const override { return 2; }
281  uint32_t width() const override { return _width; }
282  uint32_t height() const override { return _height; }
283  uint32_t depth() const override { return 1; }
284 
285  value_type* data() { return _data; }
286  const value_type* data() const { return _data; }
287 
288  inline value_type* data(size_t i) { return reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_data) + i * properties.stride); }
289  inline const value_type* data(size_t i) const { return reinterpret_cast<const value_type*>(reinterpret_cast<const uint8_t*>(_data) + i * properties.stride); }
290 
291  size_t index(uint32_t i, uint32_t j) const noexcept { return static_cast<size_t>(j) * _width + i; }
292 
293  value_type& operator[](size_t i) { return *data(i); }
294  const value_type& operator[](size_t i) const { return *data(i); }
295 
296  value_type& at(size_t i) { return *data(i); }
297  const value_type& at(size_t i) const { return *data(i); }
298 
299  value_type& operator()(uint32_t i, uint32_t j) { return *data(index(i, j)); }
300  const value_type& operator()(uint32_t i, uint32_t j) const { return *data(index(i, j)); }
301 
302  value_type& at(uint32_t i, uint32_t j) { return *data(index(i, j)); }
303  const value_type& at(uint32_t i, uint32_t j) const { return *data(index(i, j)); }
304 
305  void set(size_t i, const value_type& v) { *data(i) = v; }
306  void set(uint32_t i, uint32_t j, const value_type& v) { *data(index(i, j)) = v; }
307 
308  Data* storage() { return _storage; }
309  const Data* storage() const { return _storage; }
310 
311  iterator begin() { return iterator{_data, properties.stride}; }
312  const_iterator begin() const { return const_iterator{_data, properties.stride}; }
313 
314  iterator end() { return iterator{data(_width * _height), properties.stride}; }
315  const_iterator end() const { return const_iterator{data(_width * _height), properties.stride}; }
316 
317  protected:
318  virtual ~Array2D()
319  {
320  _delete();
321  }
322 
323  value_type* _allocate(size_t size) const
324  {
325  if (size == 0)
326  return nullptr;
327  else if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
328  return new value_type[size];
329  else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
330  return new (std::malloc(sizeof(value_type) * size)) value_type[size];
331  else
332  return new (vsg::allocate(sizeof(value_type) * size, ALLOCATOR_AFFINITY_DATA)) value_type[size];
333  }
334 
335  void _delete()
336  {
337  if (!_storage && _data)
338  {
339  if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
340  delete[] _data;
341  else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
342  std::free(_data);
343  else if (properties.allocatorType != 0)
344  vsg::deallocate(_data);
345  }
346  }
347 
348  private:
349  value_type* _data;
350  uint32_t _width;
351  uint32_t _height;
352  ref_ptr<Data> _storage;
353  };
354 
355  VSG_array2D(byteArray2D, int8_t);
356  VSG_array2D(ubyteArray2D, uint8_t);
357  VSG_array2D(shortArray2D, int16_t);
358  VSG_array2D(ushortArray2D, uint16_t);
359  VSG_array2D(intArray2D, int32_t);
360  VSG_array2D(uintArray2D, uint32_t);
361  VSG_array2D(floatArray2D, float);
362  VSG_array2D(doubleArray2D, double);
363 
364  VSG_array2D(vec2Array2D, vec2);
365  VSG_array2D(vec3Array2D, vec3);
366  VSG_array2D(vec4Array2D, vec4);
367 
368  VSG_array2D(dvec2Array2D, dvec2);
369  VSG_array2D(dvec3Array2D, dvec3);
370  VSG_array2D(dvec4Array2D, dvec4);
371 
372  VSG_array2D(bvec2Array2D, bvec2);
373  VSG_array2D(bvec3Array2D, bvec3);
374  VSG_array2D(bvec4Array2D, bvec4);
375 
376  VSG_array2D(ubvec2Array2D, ubvec2);
377  VSG_array2D(ubvec3Array2D, ubvec3);
378  VSG_array2D(ubvec4Array2D, ubvec4);
379 
380  VSG_array2D(svec2Array2D, svec2);
381  VSG_array2D(svec3Array2D, svec3);
382  VSG_array2D(svec4Array2D, svec4);
383 
384  VSG_array2D(usvec2Array2D, usvec2);
385  VSG_array2D(usvec3Array2D, usvec3);
386  VSG_array2D(usvec4Array2D, usvec4);
387 
388  VSG_array2D(ivec2Array2D, ivec2);
389  VSG_array2D(ivec3Array2D, ivec3);
390  VSG_array2D(ivec4Array2D, ivec4);
391 
392  VSG_array2D(uivec2Array2D, uivec2);
393  VSG_array2D(uivec3Array2D, uivec3);
394  VSG_array2D(uivec4Array2D, uivec4);
395 
396  VSG_array2D(block64Array2D, block64);
397  VSG_array2D(block128Array2D, block128);
398 
399 } // namespace vsg
Definition: Array2D.h:35
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition: Array2D.h:105
Definition: Data.h:110
Properties properties
properties of the data such as format, origin, stride, dataVariance etc.
Definition: Data.h:161
void dirty()
increment the ModifiedCount to signify the data has been modified
Definition: Data.h:196
Definition: ref_ptr.h:22
Definition: Data.h:116
AllocatorType allocatorType
hint as to how the data values may change during the lifetime of the vsg::Data.
Definition: Data.h:131
Definition: Data.h:66