vsg: include/vsg/core/Array2D.h Source File

vsg 1.1.9 VulkanSceneGraph library |

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