]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_query_state.cpp
Initial vogl checkin
[vogl] / src / voglcommon / vogl_query_state.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 // File: vogl_query_state.cpp
27 #include "vogl_query_state.h"
28
29 vogl_query_state::vogl_query_state()
30     : m_snapshot_handle(0),
31       m_target(GL_NONE),
32       m_prev_result(0),
33       m_has_been_begun(false),
34       m_is_valid(false)
35 {
36     VOGL_FUNC_TRACER
37 }
38
39 vogl_query_state::~vogl_query_state()
40 {
41     VOGL_FUNC_TRACER
42 }
43
44 bool vogl_query_state::snapshot(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 handle, GLenum target)
45 {
46     VOGL_FUNC_TRACER
47
48     VOGL_NOTE_UNUSED(remapper);
49     VOGL_CHECK_GL_ERROR;
50
51     clear();
52
53     VOGL_ASSERT(handle <= cUINT32_MAX);
54
55     m_snapshot_handle = static_cast<GLuint>(handle);
56     m_target = target;
57     m_has_been_begun = GL_ENTRYPOINT(glIsQuery)(static_cast<GLuint>(handle)) != 0;
58
59     if (target != GL_NONE)
60     {
61         if (context_info.supports_extension("GL_ARB_timer_query") && GL_ENTRYPOINT(glGetQueryObjecti64v))
62         {
63             GLint64 result = 0;
64             GL_ENTRYPOINT(glGetQueryObjecti64v)(m_snapshot_handle, GL_QUERY_RESULT, &result);
65             m_prev_result = result;
66         }
67         else
68         {
69             GLuint prev_result32;
70             GL_ENTRYPOINT(glGetQueryObjectuiv)(m_snapshot_handle, GL_QUERY_RESULT, &prev_result32);
71             m_prev_result = prev_result32;
72         }
73     }
74
75     m_get_result_status = vogl_check_gl_error();
76
77     m_is_valid = true;
78
79     return true;
80 }
81
82 bool vogl_query_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const
83 {
84     VOGL_FUNC_TRACER
85
86     VOGL_NOTE_UNUSED(context_info);
87
88     if (!m_is_valid)
89         return false;
90
91     bool created_handle = false;
92
93     if (!handle)
94     {
95         GLuint handle32 = 0;
96         GL_ENTRYPOINT(glGenQueries)(1, &handle32);
97         if ((vogl_check_gl_error()) || (!handle32))
98             return false;
99         handle = handle32;
100
101         remapper.declare_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle, handle, m_target);
102         VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle) == handle);
103
104         created_handle = true;
105     }
106
107     // m_target will be GL_NONE if the query has been genned but not begun up to this point.
108     if ((m_target != GL_NONE) && (m_has_been_begun))
109     {
110         GLuint prev_query = 0;
111         GL_ENTRYPOINT(glGetQueryiv)(m_target, GL_CURRENT_QUERY, reinterpret_cast<GLint *>(&prev_query));
112         VOGL_CHECK_GL_ERROR;
113
114         VOGL_ASSERT(handle <= cUINT32_MAX);
115
116         // Begin end the restore query, so it becomes a valid name.
117         GL_ENTRYPOINT(glBeginQuery)(m_target, static_cast<GLuint>(handle));
118         if (vogl_check_gl_error())
119             goto handle_error;
120
121         GL_ENTRYPOINT(glEndQuery)(m_target);
122         if (vogl_check_gl_error())
123             goto handle_error;
124
125         if (prev_query)
126         {
127             // Now begin/end the original query so it's active again. The query API sucks.
128             GL_ENTRYPOINT(glBeginQuery)(m_target, prev_query);
129             VOGL_CHECK_GL_ERROR;
130
131             GL_ENTRYPOINT(glEndQuery)(m_target);
132             VOGL_CHECK_GL_ERROR;
133         }
134     }
135
136     return true;
137
138 handle_error:
139     if ((handle) && (created_handle))
140     {
141         remapper.delete_handle_and_object(VOGL_NAMESPACE_QUERIES, m_snapshot_handle, handle);
142
143         //GLuint handle32 = static_cast<GLuint>(handle);
144         //GL_ENTRYPOINT(glDeleteQueries)(1, &handle32);
145         //VOGL_CHECK_GL_ERROR;
146
147         handle = 0;
148     }
149
150     return false;
151 }
152
153 bool vogl_query_state::remap_handles(vogl_handle_remapper &remapper)
154 {
155     VOGL_FUNC_TRACER
156
157     if (!m_is_valid)
158         return false;
159
160     m_snapshot_handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_QUERIES, m_snapshot_handle));
161
162     return true;
163 }
164
165 void vogl_query_state::clear()
166 {
167     VOGL_FUNC_TRACER
168
169     m_snapshot_handle = 0;
170     m_target = GL_NONE;
171     m_prev_result = 0;
172     m_get_result_status = GL_NONE;
173     m_has_been_begun = false;
174     m_is_valid = false;
175 }
176
177 bool vogl_query_state::serialize(json_node &node, vogl_blob_manager &blob_manager) const
178 {
179     VOGL_FUNC_TRACER
180
181     VOGL_NOTE_UNUSED(blob_manager);
182
183     if (!m_is_valid)
184         return false;
185
186     node.add_key_value("handle", m_snapshot_handle);
187     node.add_key_value("target", g_gl_enums.find_name(m_target, "gl"));
188     node.add_key_value("prev_result", m_prev_result);
189     node.add_key_value("has_been_begun", m_has_been_begun);
190
191     return true;
192 }
193
194 bool vogl_query_state::deserialize(const json_node &node, const vogl_blob_manager &blob_manager)
195 {
196     VOGL_FUNC_TRACER
197
198     VOGL_NOTE_UNUSED(blob_manager);
199
200     clear();
201
202     m_snapshot_handle = node.value_as_uint32("handle");
203     if (!m_snapshot_handle)
204     {
205         return false;
206     }
207
208     m_target = vogl_get_json_value_as_enum(node, "target");
209     if (!utils::is_in_set(static_cast<int>(m_target), GL_NONE, GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED, GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED))
210     {
211         clear();
212         return false;
213     }
214
215     m_prev_result = node.value_as_int64("prev_result");
216     m_has_been_begun = node.value_as_bool("has_been_begun");
217
218     m_is_valid = true;
219
220     return true;
221 }
222
223 bool vogl_query_state::compare_restorable_state(const vogl_gl_object_state &rhs_obj) const
224 {
225     VOGL_FUNC_TRACER
226
227     if ((!m_is_valid) || (!rhs_obj.is_valid()))
228         return false;
229
230     if (rhs_obj.get_type() != cGLSTQuery)
231         return false;
232
233     const vogl_query_state &rhs = static_cast<const vogl_query_state &>(rhs_obj);
234
235     if (this == &rhs)
236         return true;
237
238     // We can't restore the prev result, so don't bother comparing it, so there's not much to do here.
239     return (m_target == rhs.m_target) && (m_has_been_begun == rhs.m_has_been_begun);
240 }