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

vsg 1.1.3 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 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(std::forward<Args>(args)...));
96 }
97
98 ref_ptr<Object> clone(const CopyOp& copyop = {}) const override
99 {
100 return ref_ptr<Array2D>(new Array2D(*this, copyop));
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
vsg::Array2D
Definition Array2D.h:35
vsg::Array2D::clone
ref_ptr< Object > clone(const CopyOp &copyop={}) const override
Definition Array2D.h:98
vsg::Array2D::type_info
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition Array2D.h:105
vsg::CopyOp
Definition Object.h:42
vsg::Data
Definition Data.h:110
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::Data::Properties
Definition Data.h:116
vsg::Data::Properties::allocatorType
AllocatorType allocatorType
hint as to how the data values may change during the lifetime of the vsg::Data.
Definition Data.h:131
vsg::allocator_affinity_nodes
std container adapter for allocating with MEMORY_AFFINITY_NODES
Definition Allocator.h:138