]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_handle_tracker.cpp
Initial vogl checkin
[vogl] / src / voglcommon / vogl_handle_tracker.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 //----------------------------------------------------------------------------------------------------------------------
27 // File: vogl_handle_tracker.cpp
28 //----------------------------------------------------------------------------------------------------------------------
29 #include "vogl_handle_tracker.h"
30
31 vogl_handle_tracker::vogl_handle_tracker()
32 {
33     VOGL_FUNC_TRACER
34 }
35
36 vogl_handle_tracker::vogl_handle_tracker(vogl_namespace_t handle_namespace)
37     : m_namespace(handle_namespace)
38 {
39     VOGL_FUNC_TRACER
40 }
41
42 vogl_handle_tracker::~vogl_handle_tracker()
43 {
44     VOGL_FUNC_TRACER
45 }
46
47 void vogl_handle_tracker::clear()
48 {
49     VOGL_FUNC_TRACER
50
51     m_handles.clear();
52     m_inv_handles.clear();
53 }
54
55 void vogl_handle_tracker::get_handles(uint_vec &handles)
56 {
57     VOGL_FUNC_TRACER
58
59     handles.resize(0);
60     handles.reserve(m_inv_handles.size());
61
62     for (uint handle = 0; handle < m_handles.size(); handle++)
63     {
64         const handle_def &def = m_handles[handle];
65         if (def.is_valid())
66             handles.push_back(handle);
67     }
68 }
69
70 void vogl_handle_tracker::get_inv_handles(uint_vec &inv_handles)
71 {
72     VOGL_FUNC_TRACER
73
74     inv_handles.resize(0);
75     inv_handles.reserve(m_inv_handles.size());
76
77     for (uint handle = 0; handle < m_handles.size(); handle++)
78     {
79         const handle_def &def = m_handles[handle];
80         if (def.is_valid())
81             inv_handles.push_back(def.get_inv_handle());
82     }
83 }
84
85 bool vogl_handle_tracker::insert(handle_t handle, handle_t inv_handle, GLenum target)
86 {
87     VOGL_FUNC_TRACER
88
89     if (is_valid_handle(handle))
90     {
91         VOGL_ASSERT(m_handles[handle].get_inv_handle() == inv_handle);
92         VOGL_ASSERT(is_valid_inv_handle(inv_handle));
93         VOGL_ASSERT(m_inv_handles.value(inv_handle) == handle);
94         return false;
95     }
96
97     if (is_valid_inv_handle(inv_handle))
98         return false;
99
100     handle_def *pHandle = m_handles.ensure_present(handle);
101     pHandle->init(handle, inv_handle, target);
102
103     bool inv_insert_success = m_inv_handles.insert(inv_handle, handle).second;
104     VOGL_ASSERT(inv_insert_success);
105     VOGL_NOTE_UNUSED(inv_insert_success);
106
107     return true;
108 }
109
110 bool vogl_handle_tracker::conditional_update(handle_t handle, handle_t inv_handle, GLenum compare_target, GLenum target)
111 {
112     VOGL_FUNC_TRACER
113
114     if (is_valid_handle(handle))
115     {
116         handle_def &def = m_handles.get_or_create_element(handle);
117         if (def.get_target() == compare_target)
118             def.set_target(target);
119         return true;
120     }
121
122     return insert(handle, inv_handle, target);
123 }
124
125 bool vogl_handle_tracker::update(handle_t handle, handle_t inv_handle, GLenum target)
126 {
127     VOGL_FUNC_TRACER
128
129     if (is_valid_handle(handle))
130     {
131         handle_def &def = m_handles.get_or_create_element(handle);
132
133         if ((def.get_target() != GL_NONE) && (target != def.get_target()))
134             vogl_debug_printf("%s: Object target is being changed from %s to %s, handle %u inv handle %u, namespace %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(def.get_target()), g_gl_enums.find_gl_name(target), def.get_handle(), def.get_inv_handle(), vogl_get_namespace_name(m_namespace));
135
136         def.set_target(target);
137         return true;
138     }
139
140     return insert(handle, inv_handle, target);
141 }
142
143 bool vogl_handle_tracker::update_inv(handle_t inv_handle, handle_t handle, GLenum target)
144 {
145     VOGL_FUNC_TRACER
146
147     handle_t actual_handle;
148     if (map_inv_handle_to_handle(inv_handle, actual_handle))
149     {
150         VOGL_ASSERT(is_valid_handle(actual_handle));
151
152         handle_def &def = m_handles.get_or_create_element(actual_handle);
153
154         if ((def.get_target() != GL_NONE) && (target != def.get_target()))
155             vogl_debug_printf("%s: Object target is being changed from %s to %s, handle %u inv handle %u, namespace %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(def.get_target()), g_gl_enums.find_gl_name(target), def.get_handle(), def.get_inv_handle(), vogl_get_namespace_name(m_namespace));
156
157         def.set_target(target);
158
159         return true;
160     }
161
162     return insert(handle, inv_handle, target);
163 }
164
165 bool vogl_handle_tracker::set_target(handle_t handle, GLenum target)
166 {
167     VOGL_FUNC_TRACER
168
169     if (!is_valid_handle(handle))
170         return false;
171     m_handles.get_or_create_element(handle).set_target(target);
172     return true;
173 }
174
175 bool vogl_handle_tracker::set_target_inv(handle_t inv_handle, GLenum target)
176 {
177     VOGL_FUNC_TRACER
178
179     handle_hash_map_t::const_iterator it(m_inv_handles.find(inv_handle));
180     if (it == m_inv_handles.end())
181         return false;
182     return set_target(it->second, target);
183 }
184
185 bool vogl_handle_tracker::map_inv_handle_to_handle(handle_t inv_handle, handle_t &handle) const
186 {
187     VOGL_FUNC_TRACER
188
189     handle_hash_map_t::const_iterator it(m_inv_handles.find(inv_handle));
190     if (it == m_inv_handles.end())
191         return false;
192
193     handle = it->second;
194
195     VOGL_ASSERT(contains(handle));
196
197     return handle;
198 }
199
200 bool vogl_handle_tracker::map_handle_to_inv_handle(handle_t handle, handle_t &inv_handle) const
201 {
202     VOGL_FUNC_TRACER
203
204     if (handle >= m_handles.size())
205         return false;
206
207     if (!m_handles[handle].is_valid())
208         return false;
209
210     inv_handle = m_handles[handle].get_inv_handle();
211
212     VOGL_ASSERT(contains_inv(inv_handle));
213
214     return true;
215 }
216
217 GLenum vogl_handle_tracker::get_target(handle_t handle) const
218 {
219     VOGL_FUNC_TRACER
220
221     if (!is_valid_handle(handle))
222         return GL_NONE;
223     return m_handles[handle].get_target();
224 }
225
226 GLenum vogl_handle_tracker::get_target_inv(handle_t inv_handle) const
227 {
228     VOGL_FUNC_TRACER
229
230     handle_t handle;
231     if (!map_inv_handle_to_handle(inv_handle, handle))
232         return GL_NONE;
233     VOGL_ASSERT(is_valid_handle(handle));
234     return m_handles[handle].get_target();
235 }
236
237 bool vogl_handle_tracker::erase(handle_t handle)
238 {
239     VOGL_FUNC_TRACER
240
241     if (!is_valid_handle(handle))
242         return false;
243
244     VOGL_ASSERT(m_handles[handle].get_handle() == handle);
245
246     uint inv_handle = m_handles[handle].get_inv_handle();
247
248     VOGL_ASSERT(m_inv_handles.value(inv_handle) == handle);
249
250     m_handles.get_or_create_element(handle).clear();
251     VOGL_ASSERT(!m_handles[handle].is_valid());
252
253     bool success = m_inv_handles.erase(inv_handle);
254     VOGL_NOTE_UNUSED(success);
255     VOGL_ASSERT(success);
256
257     return true;
258 }
259
260 bool vogl_handle_tracker::erase_inv(handle_t inv_handle)
261 {
262     VOGL_FUNC_TRACER
263
264     handle_hash_map_t::const_iterator it(m_inv_handles.find(inv_handle));
265     if (it == m_inv_handles.end())
266         return false;
267
268     uint handle = it->second;
269     if (!is_valid_handle(handle))
270     {
271         VOGL_ASSERT_ALWAYS;
272     }
273     else
274     {
275         VOGL_ASSERT(m_handles[handle].get_handle() == handle);
276         VOGL_ASSERT(m_handles[handle].get_inv_handle() == inv_handle);
277         m_handles.get_or_create_element(handle).clear();
278         VOGL_ASSERT(!m_handles[handle].is_valid());
279     }
280
281     m_inv_handles.erase(inv_handle);
282     return true;
283 }
284
285 bool vogl_handle_tracker::invert(vogl_handle_tracker &inverted_map) const
286 {
287     VOGL_FUNC_TRACER
288
289     inverted_map.clear();
290
291     for (uint handle = 0; handle < m_handles.size(); handle++)
292     {
293         const handle_def &def = m_handles[handle];
294         if (!def.is_valid())
295             continue;
296
297         if (!inverted_map.insert(def.get_inv_handle(), def.get_handle(), def.get_target()))
298             return false;
299     }
300
301     return true;
302 }
303
304 bool vogl_handle_tracker::check() const
305 {
306     VOGL_FUNC_TRACER
307
308     handle_hash_map_t forward_to_inverse_map;
309     forward_to_inverse_map.reserve(m_inv_handles.size());
310     for (handle_hash_map_t::const_iterator it = m_inv_handles.begin(); it != m_inv_handles.end(); ++it)
311         if (!forward_to_inverse_map.insert(it->second, it->first).second)
312             return false;
313
314     uint total_found = 0;
315     for (uint handle = 0; handle < m_handles.size(); handle++)
316     {
317         if (!m_handles.is_present(handle))
318         {
319             if (forward_to_inverse_map.contains(handle))
320                 return false;
321             continue;
322         }
323
324         const handle_def &def = m_handles[handle];
325         if (!def.is_valid())
326         {
327             if (forward_to_inverse_map.contains(handle))
328                 return false;
329             continue;
330         }
331
332         const uint *pInv_handle = forward_to_inverse_map.find_value(handle);
333         if (!pInv_handle)
334             return false;
335
336         uint inv_handle = *pInv_handle;
337
338         if (m_inv_handles.value(inv_handle) != handle)
339             return false;
340
341         if (def.get_handle() != handle)
342             return false;
343         if (def.get_inv_handle() != inv_handle)
344             return false;
345
346         total_found++;
347     }
348
349     if (total_found != m_inv_handles.size())
350         return false;
351
352     return true;
353 }
354
355 bool vogl_handle_tracker::operator==(const vogl_handle_tracker &other) const
356 {
357     VOGL_FUNC_TRACER
358
359     if (m_inv_handles != other.m_inv_handles)
360         return false;
361
362     if (m_handles != other.m_handles)
363         return false;
364
365     return true;
366 }
367
368 bool vogl_handle_tracker::serialize(json_node &node) const
369 {
370     VOGL_FUNC_TRACER
371
372     node.init_array();
373
374     for (uint i = 0; i < m_handles.size(); i++)
375     {
376         if (!is_valid_handle(i))
377             continue;
378
379         json_node &obj = node.add_object();
380         obj.add_key_value("handle", m_handles[i].get_handle());
381         obj.add_key_value("inv_handle", m_handles[i].get_inv_handle());
382         obj.add_key_value("target", m_handles[i].get_target());
383     }
384
385     return true;
386 }
387
388 bool vogl_handle_tracker::deserialize(const json_node &node)
389 {
390     VOGL_FUNC_TRACER
391
392     clear();
393
394     for (uint i = 0; i < node.size(); i++)
395     {
396         const json_node *pObj = node.get_child(i);
397         if ((!pObj) || (!pObj->is_object()))
398             return false;
399
400         uint handle, inv_handle;
401         GLenum target;
402         if (!pObj->get_value_as_uint32("handle", handle) || !pObj->get_value_as_uint32("inv_handle", inv_handle) || !pObj->get_value_as_uint32("target", target))
403             return false;
404
405         if (!insert(handle, inv_handle, target))
406             return false;
407     }
408
409     return true;
410 }