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 #include "vogleditor_apicalltimelinemodel.h"
28 vogleditor_apiCallTimelineModel::vogleditor_apiCallTimelineModel(vogleditor_apiCallTreeItem* pRootApiCall) :
29 m_pRootApiCall(pRootApiCall),
35 void vogleditor_apiCallTimelineModel::refresh()
37 if (m_pRootApiCall == NULL)
43 float timelineStart = 0;
44 float timelineEnd = 1;
45 m_rawBaseTime = timelineStart;
47 int numChildren = m_pRootApiCall->childCount();
50 uint64_t firstStart = 0;
51 uint64_t firstEnd = 0;
52 m_pRootApiCall->child(0)->frameItem()->getStartEndTimes(firstStart, firstEnd);
54 uint64_t lastStart = 0;
56 vogleditor_apiCallTreeItem* pLastChild = m_pRootApiCall->child(numChildren-1);
57 pLastChild->frameItem()->getStartEndTimes(lastStart, lastEnd);
59 m_rawBaseTime = firstStart;
60 timelineStart = u64ToFloat(firstStart - m_rawBaseTime);
61 timelineEnd = u64ToFloat(lastEnd - m_rawBaseTime);
64 // see if we actually have to update some of this stuff
65 bool skipCreation = false;
66 if (m_rootItem != NULL)
68 if (m_rootItem->getDuration() == timelineEnd - timelineStart &&
69 m_rootItem->childCount() == numChildren)
71 // no need to make a new root
78 if (m_rootItem != NULL)
83 m_rootItem = new vogleditor_timelineItem(timelineStart, timelineEnd);
85 // add markers for the start of each frame
87 for (int c = 0; c < numChildren; c++)
89 vogleditor_apiCallTreeItem* pFrameItem = m_pRootApiCall->child(c);
90 if (pFrameItem->childCount() > 0)
92 frameStart = u64ToFloat(pFrameItem->child(0)->apiCallItem()->startTime() - m_rawBaseTime);
93 vogleditor_timelineItem* pFrameTimelineItem = new vogleditor_timelineItem(frameStart, m_rootItem);
94 pFrameTimelineItem->setFrameItem(pFrameItem->frameItem());
95 m_rootItem->appendChild(pFrameTimelineItem);
99 // if we get here, we are at a frame that had no api calls
103 // recursively add each children
104 for (int frameIndex = 0; frameIndex < numChildren; frameIndex++)
106 vogleditor_apiCallTreeItem* pFrameChild = m_pRootApiCall->child(frameIndex);
108 AddApiCallsToTimeline(pFrameChild, m_rootItem);
113 float vogleditor_apiCallTimelineModel::u64ToFloat(uint64_t value)
115 // taken from: http://stackoverflow.com/questions/4400747/converting-from-unsigned-long-long-to-float-with-round-to-nearest-even
116 const int mask_bit_count = 31;
118 // How many bits are needed?
119 int b = sizeof(uint64_t) * CHAR_BIT - 1;
122 if(value & (1ull << b))
128 // If there are few enough significant bits, use normal cast and done.
129 if(b < mask_bit_count)
131 return static_cast<float>(value & ~1ull);
134 // Save off the low-order useless bits:
135 uint64_t low_bits = value & ((1ull << (b - mask_bit_count)) - 1);
137 // Now mask away those useless low bits:
138 value &= ~((1ull << (b - mask_bit_count)) - 1);
140 // Finally, decide how to round the new LSB:
141 if(low_bits > ((1ull << (b - mask_bit_count)) / 2ull))
144 value |= (1ull << (b - mask_bit_count));
149 value &= ~(1ull << (b - mask_bit_count));
152 return static_cast<float>(value);
155 void vogleditor_apiCallTimelineModel::AddApiCallsToTimeline(vogleditor_apiCallTreeItem* pRoot, vogleditor_timelineItem* pDestRoot)
157 int numChildren = pRoot->childCount();
158 for (int c = 0; c < numChildren; c++)
160 vogleditor_apiCallTreeItem* pChild = pRoot->child(c);
161 if (pChild->apiCallItem() != NULL)
163 float beginFloat = u64ToFloat(pChild->apiCallItem()->startTime() - m_rawBaseTime);
164 float endFloat = u64ToFloat(pChild->apiCallItem()->endTime() - m_rawBaseTime);
166 vogleditor_timelineItem* pNewItem = new vogleditor_timelineItem(beginFloat, endFloat, pDestRoot);
167 pNewItem->setApiCallItem(pChild->apiCallItem());
168 pDestRoot->appendChild(pNewItem);
169 AddApiCallsToTimeline(pChild, pNewItem);