Panda3D

vertexDataBuffer.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file vertexDataBuffer.cxx
10 * @author drose
11 * @date 2007-05-14
12 */
13
14 #include "vertexDataBuffer.h"
15 #include "config_gobj.h"
16 #include "pStatTimer.h"
17
18 TypeHandle VertexDataBuffer::_type_handle;
19
20 /**
21 *
22 */
23 void VertexDataBuffer::
24 operator = (const VertexDataBuffer &copy) {
25 LightMutexHolder holder(_lock);
26 LightMutexHolder holder2(copy._lock);
27
28 if (_resident_data != nullptr) {
29 nassertv(_reserved_size != 0);
30 get_class_type().deallocate_array(_resident_data);
31 _resident_data = nullptr;
32 }
33 if (copy._resident_data != nullptr && copy._size != 0) {
34 // We only allocate _size bytes, not the full _reserved_size allocated by
35 // the original copy.
36 _resident_data = (unsigned char *)get_class_type().allocate_array(copy._size);
37 memcpy(_resident_data, copy._resident_data, copy._size);
38 }
39 _size = copy._size;
40 _reserved_size = copy._size;
41 _block = copy._block;
42 nassertv(_reserved_size >= _size);
43 }
44
45 /**
46 * Swaps the data buffers between this one and the other one.
47 */
48 void VertexDataBuffer::
49 swap(VertexDataBuffer &other) {
50 LightMutexHolder holder(_lock);
51 LightMutexHolder holder2(other._lock);
52
53 unsigned char *resident_data = _resident_data;
54 size_t size = _size;
55 size_t reserved_size = _reserved_size;
56
57 _block.swap(other._block);
58
59 _resident_data = other._resident_data;
60 _size = other._size;
61 _reserved_size = other._reserved_size;
62
63 other._resident_data = resident_data;
64 other._size = size;
65 other._reserved_size = reserved_size;
66 nassertv(_reserved_size >= _size);
67 }
68
69 /**
70 * Changes the reserved size of the buffer, preserving its data (except for
71 * any data beyond the new end of the buffer, if the buffer is being reduced).
72 * If the buffer is expanded, the new data is uninitialized.
73 *
74 * Assumes the lock is already held.
75 */
76 void VertexDataBuffer::
77 do_clean_realloc(size_t reserved_size) {
78 if (reserved_size != _reserved_size) {
79 if (reserved_size == 0 || _size == 0) {
80 do_unclean_realloc(reserved_size);
81 return;
82 }
83
84 if (gobj_cat.is_debug()) {
85 gobj_cat.debug()
86 << this << ".clean_realloc(" << reserved_size << ")\n";
87 }
88
89 // Page in if we're currently paged out.
90 if (_reserved_size != 0 && _resident_data == nullptr) {
91 do_page_in();
92 }
93
94 if (_reserved_size == 0) {
95 nassertv(_resident_data == nullptr);
96 _resident_data = (unsigned char *)get_class_type().allocate_array(reserved_size);
97 } else {
98 nassertv(_resident_data != nullptr);
99 _resident_data = (unsigned char *)get_class_type().reallocate_array(_resident_data, reserved_size);
100 }
101 nassertv(_resident_data != nullptr);
102 _reserved_size = reserved_size;
103 }
104
105 _size = std::min(_size, _reserved_size);
106 }
107
108 /**
109 * Changes the reserved size of the buffer, without regard to preserving its
110 * data. This implicitly resets the size to 0.
111 *
112 * Assumes the lock is already held.
113 */
114 void VertexDataBuffer::
115 do_unclean_realloc(size_t reserved_size) {
116 if (reserved_size != _reserved_size || _resident_data == nullptr) {
117 if (gobj_cat.is_debug()) {
118 gobj_cat.debug()
119 << this << ".unclean_realloc(" << reserved_size << ")\n";
120 }
121
122 // If we're paged out, discard the page.
123 _block = nullptr;
124
125 if (_resident_data != nullptr) {
126 nassertv(_reserved_size != 0);
127
128 get_class_type().deallocate_array(_resident_data);
129 _resident_data = nullptr;
130 _reserved_size = 0;
131 }
132
133 if (reserved_size != 0) {
134 nassertv(_resident_data == nullptr);
135 _resident_data = (unsigned char *)get_class_type().allocate_array(reserved_size);
136 }
137
138 _reserved_size = reserved_size;
139 }
140
141 _size = 0;
142 }
143
144 /**
145 * Moves the buffer out of independent memory and puts it on a page in the
146 * indicated book. The buffer may still be directly accessible as long as its
147 * page remains resident. Any subsequent attempt to rewrite the buffer will
148 * implicitly move it off of the page and back into independent memory.
149 *
150 * Assumes the lock is already held.
151 */
152 void VertexDataBuffer::
153 do_page_out(VertexDataBook &book) {
154 if (_block != nullptr || _reserved_size == 0) {
155 // We're already paged out.
156 return;
157 }
158 nassertv(_resident_data != nullptr);
159
160 if (_size == 0) {
161 // It's an empty buffer. Just deallocate it; don't bother to create a
162 // block.
163 get_class_type().deallocate_array(_resident_data);
164 _resident_data = nullptr;
165 _reserved_size = 0;
166
167 } else {
168 // It's a nonempty buffer, so write _size bytes (but not the full
169 // _reserved_size bytes) to a block.
170 _block = book.alloc(_size);
171 nassertv(_block != nullptr);
172 unsigned char *pointer = _block->get_pointer(true);
173 nassertv(pointer != nullptr);
174 memcpy(pointer, _resident_data, _size);
175
176 get_class_type().deallocate_array(_resident_data);
177 _resident_data = nullptr;
178
179 _reserved_size = _size;
180 }
181 nassertv(_reserved_size >= _size);
182 }
183
184 /**
185 * Moves the buffer off of its current page and into independent memory. If
186 * the page is not already resident, it is forced resident first.
187 *
188 * Assumes the lock is already held.
189 */
190 void VertexDataBuffer::
191 do_page_in() {
192 if (_resident_data != nullptr || _reserved_size == 0) {
193 // We're already paged in.
194 return;
195 }
196
197 nassertv(_block != nullptr);
198 nassertv(_reserved_size == _size);
199
200 _resident_data = (unsigned char *)get_class_type().allocate_array(_size);
201 nassertv(_resident_data != nullptr);
202
203 memcpy(_resident_data, _block->get_pointer(true), _size);
204 }
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypeHandle::deallocate_array
void deallocate_array(void *ptr)
Deallocates memory, subtracting it from the total amount of memory allocated for this type.
Definition: typeHandle.cxx:141
TypeHandle::reallocate_array
void * reallocate_array(void *ptr, size_t size)
Reallocates memory, adjusting the total amount of memory allocated for this type.
Definition: typeHandle.cxx:115
TypeHandle::allocate_array
void * allocate_array(size_t size)
Allocates memory, adding it to the total amount of memory allocated for this type.
Definition: typeHandle.cxx:88
VertexDataBook
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects.
Definition: vertexDataBook.h:30
VertexDataBook::alloc
VertexDataBlock * alloc(size_t size)
Allocates and returns a new VertexDataBuffer of the requested size.
Definition: vertexDataBook.I:18
VertexDataBuffer
A block of bytes that stores the actual raw vertex data referenced by a GeomVertexArrayData object.
Definition: vertexDataBuffer.h:52
VertexDataBuffer::swap
void swap(VertexDataBuffer &other)
Swaps the data buffers between this one and the other one.
Definition: vertexDataBuffer.cxx:49
config_gobj.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
vertexDataBuffer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.