1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 **************************************************************************/
26 //----------------------------------------------------------------------------------------------------------------------
27 // File: vogl_handle_tracker.cpp
28 //----------------------------------------------------------------------------------------------------------------------
29 #include "vogl_handle_tracker.h"
31 vogl_handle_tracker::vogl_handle_tracker()
36 vogl_handle_tracker::vogl_handle_tracker(vogl_namespace_t handle_namespace)
37 : m_namespace(handle_namespace)
42 vogl_handle_tracker::~vogl_handle_tracker()
47 void vogl_handle_tracker::clear()
52 m_inv_handles.clear();
55 void vogl_handle_tracker::get_handles(uint_vec &handles)
60 handles.reserve(m_inv_handles.size());
62 for (uint handle = 0; handle < m_handles.size(); handle++)
64 const handle_def &def = m_handles[handle];
66 handles.push_back(handle);
70 void vogl_handle_tracker::get_inv_handles(uint_vec &inv_handles)
74 inv_handles.resize(0);
75 inv_handles.reserve(m_inv_handles.size());
77 for (uint handle = 0; handle < m_handles.size(); handle++)
79 const handle_def &def = m_handles[handle];
81 inv_handles.push_back(def.get_inv_handle());
85 bool vogl_handle_tracker::insert(handle_t handle, handle_t inv_handle, GLenum target)
89 if (is_valid_handle(handle))
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);
97 if (is_valid_inv_handle(inv_handle))
100 handle_def *pHandle = m_handles.ensure_present(handle);
101 pHandle->init(handle, inv_handle, target);
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);
110 bool vogl_handle_tracker::conditional_update(handle_t handle, handle_t inv_handle, GLenum compare_target, GLenum target)
114 if (is_valid_handle(handle))
116 handle_def &def = m_handles.get_or_create_element(handle);
117 if (def.get_target() == compare_target)
118 def.set_target(target);
122 return insert(handle, inv_handle, target);
125 bool vogl_handle_tracker::update(handle_t handle, handle_t inv_handle, GLenum target)
129 if (is_valid_handle(handle))
131 handle_def &def = m_handles.get_or_create_element(handle);
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));
136 def.set_target(target);
140 return insert(handle, inv_handle, target);
143 bool vogl_handle_tracker::update_inv(handle_t inv_handle, handle_t handle, GLenum target)
147 handle_t actual_handle;
148 if (map_inv_handle_to_handle(inv_handle, actual_handle))
150 VOGL_ASSERT(is_valid_handle(actual_handle));
152 handle_def &def = m_handles.get_or_create_element(actual_handle);
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));
157 def.set_target(target);
162 return insert(handle, inv_handle, target);
165 bool vogl_handle_tracker::set_target(handle_t handle, GLenum target)
169 if (!is_valid_handle(handle))
171 m_handles.get_or_create_element(handle).set_target(target);
175 bool vogl_handle_tracker::set_target_inv(handle_t inv_handle, GLenum target)
179 handle_hash_map_t::const_iterator it(m_inv_handles.find(inv_handle));
180 if (it == m_inv_handles.end())
182 return set_target(it->second, target);
185 bool vogl_handle_tracker::map_inv_handle_to_handle(handle_t inv_handle, handle_t &handle) const
189 handle_hash_map_t::const_iterator it(m_inv_handles.find(inv_handle));
190 if (it == m_inv_handles.end())
195 VOGL_ASSERT(contains(handle));
200 bool vogl_handle_tracker::map_handle_to_inv_handle(handle_t handle, handle_t &inv_handle) const
204 if (handle >= m_handles.size())
207 if (!m_handles[handle].is_valid())
210 inv_handle = m_handles[handle].get_inv_handle();
212 VOGL_ASSERT(contains_inv(inv_handle));
217 GLenum vogl_handle_tracker::get_target(handle_t handle) const
221 if (!is_valid_handle(handle))
223 return m_handles[handle].get_target();
226 GLenum vogl_handle_tracker::get_target_inv(handle_t inv_handle) const
231 if (!map_inv_handle_to_handle(inv_handle, handle))
233 VOGL_ASSERT(is_valid_handle(handle));
234 return m_handles[handle].get_target();
237 bool vogl_handle_tracker::erase(handle_t handle)
241 if (!is_valid_handle(handle))
244 VOGL_ASSERT(m_handles[handle].get_handle() == handle);
246 uint inv_handle = m_handles[handle].get_inv_handle();
248 VOGL_ASSERT(m_inv_handles.value(inv_handle) == handle);
250 m_handles.get_or_create_element(handle).clear();
251 VOGL_ASSERT(!m_handles[handle].is_valid());
253 bool success = m_inv_handles.erase(inv_handle);
254 VOGL_NOTE_UNUSED(success);
255 VOGL_ASSERT(success);
260 bool vogl_handle_tracker::erase_inv(handle_t inv_handle)
264 handle_hash_map_t::const_iterator it(m_inv_handles.find(inv_handle));
265 if (it == m_inv_handles.end())
268 uint handle = it->second;
269 if (!is_valid_handle(handle))
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());
281 m_inv_handles.erase(inv_handle);
285 bool vogl_handle_tracker::invert(vogl_handle_tracker &inverted_map) const
289 inverted_map.clear();
291 for (uint handle = 0; handle < m_handles.size(); handle++)
293 const handle_def &def = m_handles[handle];
297 if (!inverted_map.insert(def.get_inv_handle(), def.get_handle(), def.get_target()))
304 bool vogl_handle_tracker::check() const
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)
314 uint total_found = 0;
315 for (uint handle = 0; handle < m_handles.size(); handle++)
317 if (!m_handles.is_present(handle))
319 if (forward_to_inverse_map.contains(handle))
324 const handle_def &def = m_handles[handle];
327 if (forward_to_inverse_map.contains(handle))
332 const uint *pInv_handle = forward_to_inverse_map.find_value(handle);
336 uint inv_handle = *pInv_handle;
338 if (m_inv_handles.value(inv_handle) != handle)
341 if (def.get_handle() != handle)
343 if (def.get_inv_handle() != inv_handle)
349 if (total_found != m_inv_handles.size())
355 bool vogl_handle_tracker::operator==(const vogl_handle_tracker &other) const
359 if (m_inv_handles != other.m_inv_handles)
362 if (m_handles != other.m_handles)
368 bool vogl_handle_tracker::serialize(json_node &node) const
374 for (uint i = 0; i < m_handles.size(); i++)
376 if (!is_valid_handle(i))
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());
388 bool vogl_handle_tracker::deserialize(const json_node &node)
394 for (uint i = 0; i < node.size(); i++)
396 const json_node *pObj = node.get_child(i);
397 if ((!pObj) || (!pObj->is_object()))
400 uint handle, inv_handle;
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))
405 if (!insert(handle, inv_handle, target))