]> git.cworth.org Git - vogl/blob - src/vogleditor/vogleditor_apicalltimelinemodel.cpp
Initial vogl checkin
[vogl] / src / vogleditor / vogleditor_apicalltimelinemodel.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 #include "vogleditor_apicalltimelinemodel.h"
27
28 vogleditor_apiCallTimelineModel::vogleditor_apiCallTimelineModel(vogleditor_apiCallTreeItem* pRootApiCall) :
29    m_pRootApiCall(pRootApiCall),
30    m_rawBaseTime(0)
31 {
32    refresh();
33 }
34
35 void vogleditor_apiCallTimelineModel::refresh()
36 {
37    if (m_pRootApiCall == NULL)
38    {
39       return;
40    }
41
42
43    float timelineStart = 0;
44    float timelineEnd = 1;
45    m_rawBaseTime = timelineStart;
46
47    int numChildren = m_pRootApiCall->childCount();
48    if (numChildren > 0)
49    {
50        uint64_t firstStart = 0;
51        uint64_t firstEnd = 0;
52        m_pRootApiCall->child(0)->frameItem()->getStartEndTimes(firstStart, firstEnd);
53
54        uint64_t lastStart = 0;
55        uint64_t lastEnd = 0;
56        vogleditor_apiCallTreeItem* pLastChild = m_pRootApiCall->child(numChildren-1);
57        pLastChild->frameItem()->getStartEndTimes(lastStart, lastEnd);
58
59        m_rawBaseTime = firstStart;
60        timelineStart = u64ToFloat(firstStart - m_rawBaseTime);
61        timelineEnd = u64ToFloat(lastEnd - m_rawBaseTime);
62    }
63
64    // see if we actually have to update some of this stuff
65    bool skipCreation = false;
66    if (m_rootItem != NULL)
67    {
68       if (m_rootItem->getDuration() == timelineEnd - timelineStart &&
69           m_rootItem->childCount() == numChildren)
70       {
71          // no need to make a new root
72          skipCreation = true;
73       }
74    }
75
76    if (!skipCreation)
77    {
78       if (m_rootItem != NULL)
79       {
80          delete m_rootItem;
81       }
82
83       m_rootItem = new vogleditor_timelineItem(timelineStart, timelineEnd);
84
85       // add markers for the start of each frame
86       float frameStart = 0;
87       for (int c = 0; c < numChildren; c++)
88       {
89          vogleditor_apiCallTreeItem* pFrameItem = m_pRootApiCall->child(c);
90          if (pFrameItem->childCount() > 0)
91          {
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);
96          }
97          else
98          {
99             // if we get here, we are at a frame that had no api calls
100          }
101       }
102
103       // recursively add each children
104       for (int frameIndex = 0; frameIndex < numChildren; frameIndex++)
105       {
106          vogleditor_apiCallTreeItem* pFrameChild = m_pRootApiCall->child(frameIndex);
107
108          AddApiCallsToTimeline(pFrameChild, m_rootItem);
109       }
110    }
111 }
112
113 float vogleditor_apiCallTimelineModel::u64ToFloat(uint64_t value)
114 {
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;
117
118     // How many bits are needed?
119     int b = sizeof(uint64_t) * CHAR_BIT - 1;
120     for(; b >= 0; --b)
121     {
122         if(value & (1ull << b))
123         {
124             break;
125         }
126     }
127
128     // If there are few enough significant bits, use normal cast and done.
129     if(b < mask_bit_count)
130     {
131         return static_cast<float>(value & ~1ull);
132     }
133
134     // Save off the low-order useless bits:
135     uint64_t low_bits = value & ((1ull << (b - mask_bit_count)) - 1);
136
137     // Now mask away those useless low bits:
138     value &= ~((1ull << (b - mask_bit_count)) - 1);
139
140     // Finally, decide how to round the new LSB:
141     if(low_bits > ((1ull << (b - mask_bit_count)) / 2ull))
142     {
143         // Round up.
144         value |= (1ull << (b - mask_bit_count));
145     }
146     else
147     {
148         // Round down.
149         value &= ~(1ull << (b - mask_bit_count));
150     }
151
152     return static_cast<float>(value);
153 }
154
155 void vogleditor_apiCallTimelineModel::AddApiCallsToTimeline(vogleditor_apiCallTreeItem* pRoot, vogleditor_timelineItem* pDestRoot)
156 {
157    int numChildren = pRoot->childCount();
158    for (int c = 0; c < numChildren; c++)
159    {
160       vogleditor_apiCallTreeItem* pChild = pRoot->child(c);
161       if (pChild->apiCallItem() != NULL)
162       {
163           float beginFloat = u64ToFloat(pChild->apiCallItem()->startTime() - m_rawBaseTime);
164           float endFloat = u64ToFloat(pChild->apiCallItem()->endTime() - m_rawBaseTime);
165
166           vogleditor_timelineItem* pNewItem = new vogleditor_timelineItem(beginFloat, endFloat, pDestRoot);
167           pNewItem->setApiCallItem(pChild->apiCallItem());
168           pDestRoot->appendChild(pNewItem);
169           AddApiCallsToTimeline(pChild, pNewItem);
170       }
171    }
172 }