• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer
3  * Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 /**
22  * SECTION:gstglquery
23  * @short_description: OpenGL query abstraction
24  * @title: GstGLQuery
25  *
26  * A #GstGLQuery represents and holds an OpenGL query object.  Various types of
27  * queries can be run or counters retrieved.
28  *
29  * Since: 1.10
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include <string.h>
37 
38 #include "gstglquery.h"
39 
40 #include "gstglcontext.h"
41 #include "gstglfuncs.h"
42 
43 #ifndef GL_TIME_ELAPSED
44 #define GL_TIME_ELAPSED 0x88BF
45 #endif
46 
47 #ifndef GL_TIMESTAMP
48 #define GL_TIMESTAMP 0x8E28
49 #endif
50 
51 #ifndef GL_QUERY_RESULT
52 #define GL_QUERY_RESULT 0x8866
53 #endif
54 
55 #define GST_CAT_DEFAULT gst_gl_query_debug
56 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
57 
58 static void
_init_debug(void)59 _init_debug (void)
60 {
61   static gsize _init = 0;
62 
63   if (g_once_init_enter (&_init)) {
64     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glquery", 0, "glquery element");
65     g_once_init_leave (&_init, 1);
66   }
67 }
68 
69 static const gchar *
_query_type_to_string(guint query_type)70 _query_type_to_string (guint query_type)
71 {
72   switch (query_type) {
73     case GST_GL_QUERY_TIME_ELAPSED:
74     case GL_TIME_ELAPSED:
75       return "time elapsed";
76     case GL_TIMESTAMP:
77     case GST_GL_QUERY_TIMESTAMP:
78       return "timestamp";
79     default:
80       return "unknown";
81   }
82 }
83 
84 static guint
_gst_gl_query_type_to_gl(GstGLQueryType query_type)85 _gst_gl_query_type_to_gl (GstGLQueryType query_type)
86 {
87   if (query_type == GST_GL_QUERY_TIME_ELAPSED)
88     return GL_TIME_ELAPSED;
89   if (query_type == GST_GL_QUERY_TIMESTAMP)
90     return GL_TIMESTAMP;
91 
92   return 0;
93 }
94 
95 static gboolean
_query_type_supports_counter(guint gl_query_type)96 _query_type_supports_counter (guint gl_query_type)
97 {
98   return gl_query_type == GL_TIMESTAMP;
99 }
100 
101 static gboolean
_query_type_supports_begin_end(guint gl_query_type)102 _query_type_supports_begin_end (guint gl_query_type)
103 {
104   return gl_query_type == GL_TIME_ELAPSED;
105 }
106 
107 static gboolean
_context_supports_query_type(GstGLContext * context,guint gl_query_type)108 _context_supports_query_type (GstGLContext * context, guint gl_query_type)
109 {
110   return gl_query_type != 0 && context->gl_vtable->GenQueries != NULL;
111 }
112 
113 static gchar *
_log_time(gpointer user_data)114 _log_time (gpointer user_data)
115 {
116   GstGLQuery *query = user_data;
117   guint64 result = 0;
118 
119   result = gst_gl_query_result (query);
120 
121   return gst_info_strdup_printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (result));
122 }
123 
124 /**
125  * gst_gl_query_init:
126  * @query: a #GstGLQuery
127  * @context: a #GstGLContext
128  * @query_type: the #GstGLQueryType
129  *
130  * Since: 1.10
131  */
132 void
gst_gl_query_init(GstGLQuery * query,GstGLContext * context,GstGLQueryType query_type)133 gst_gl_query_init (GstGLQuery * query, GstGLContext * context,
134     GstGLQueryType query_type)
135 {
136   const GstGLFuncs *gl;
137   GLenum gl_query_type;
138 
139   g_return_if_fail (query != NULL);
140   g_return_if_fail (GST_IS_GL_CONTEXT (context));
141   gl = context->gl_vtable;
142   gl_query_type = _gst_gl_query_type_to_gl (query_type);
143   g_return_if_fail (gl_query_type != GL_NONE);
144 
145   memset (query, 0, sizeof (*query));
146 
147   _init_debug ();
148 
149   query->query_type = gl_query_type;
150   query->context = gst_object_ref (context);
151   query->supported = _context_supports_query_type (context, query->query_type);
152 
153   if (query->supported)
154     gl->GenQueries (1, &query->query_id);
155 
156   gst_gl_async_debug_init (&query->debug);
157   query->debug.callback = _log_time;
158   query->debug.user_data = query;
159 }
160 
161 /**
162  * gst_gl_query_unset:
163  * @query: a #GstGLQuery
164  *
165  * Free any dynamically allocated resources
166  *
167  * Since: 1.10
168  */
169 void
gst_gl_query_unset(GstGLQuery * query)170 gst_gl_query_unset (GstGLQuery * query)
171 {
172   const GstGLFuncs *gl;
173 
174   g_return_if_fail (query != NULL);
175   if (query->start_called)
176     g_critical ("Unsetting a running query. This may not be what you wanted."
177         "Be sure to pair calls to gst_gl_query_start() and gst_gl_query_end()");
178 
179   GST_TRACE ("%p unsetting query %u", query, query->query_id);
180 
181   gl = query->context->gl_vtable;
182 
183   /* unset the debug object as it may callback to print the last message */
184   gst_gl_async_debug_unset (&query->debug);
185 
186   if (query->query_id)
187     gl->DeleteQueries (1, &query->query_id);
188 
189   gst_object_unref (query->context);
190 }
191 
192 /**
193  * gst_gl_query_new: (skip)
194  * @context: a #GstGLContext
195  * @query_type: the #GstGLQueryType to create
196  *
197  * Free with gst_gl_query_free()
198  *
199  * Returns: a new #GstGLQuery
200  *
201  * Since: 1.10
202  */
203 GstGLQuery *
gst_gl_query_new(GstGLContext * context,GstGLQueryType query_type)204 gst_gl_query_new (GstGLContext * context, GstGLQueryType query_type)
205 {
206   GstGLQuery *query = g_new0 (GstGLQuery, 1);
207 
208   gst_gl_query_init (query, context, query_type);
209 
210   return query;
211 }
212 
213 /**
214  * gst_gl_query_free:
215  * @query: a #GstGLQuery
216  *
217  * Frees a #GstGLQuery
218  *
219  * Since: 1.10
220  */
221 void
gst_gl_query_free(GstGLQuery * query)222 gst_gl_query_free (GstGLQuery * query)
223 {
224   g_return_if_fail (query != NULL);
225 
226   gst_gl_query_unset (query);
227   g_free (query);
228 }
229 
230 /**
231  * gst_gl_query_start:
232  * @query: a #GstGLQuery
233  *
234  * Start counting the query
235  *
236  * Since: 1.10
237  */
238 void
gst_gl_query_start(GstGLQuery * query)239 gst_gl_query_start (GstGLQuery * query)
240 {
241   const GstGLFuncs *gl;
242 
243   g_return_if_fail (query != NULL);
244   g_return_if_fail (_query_type_supports_begin_end (query->query_type));
245   g_return_if_fail (query->start_called == FALSE);
246 
247   query->start_called = TRUE;
248 
249   if (!query->supported)
250     return;
251 
252   gst_gl_async_debug_output_log_msg (&query->debug);
253 
254   GST_TRACE ("%p start query type \'%s\' id %u", query,
255       _query_type_to_string (query->query_type), query->query_id);
256 
257   gl = query->context->gl_vtable;
258   gl->BeginQuery (query->query_type, query->query_id);
259 }
260 
261 /**
262  * gst_gl_query_end:
263  * @query: a #GstGLQuery
264  *
265  * End counting the query
266  *
267  * Since: 1.10
268  */
269 void
gst_gl_query_end(GstGLQuery * query)270 gst_gl_query_end (GstGLQuery * query)
271 {
272   const GstGLFuncs *gl;
273 
274   g_return_if_fail (query != NULL);
275   g_return_if_fail (_query_type_supports_begin_end (query->query_type));
276   g_return_if_fail (query->start_called);
277 
278   query->start_called = FALSE;
279 
280   if (!query->supported)
281     return;
282 
283   GST_TRACE ("%p end query type \'%s\' id %u", query,
284       _query_type_to_string (query->query_type), query->query_id);
285 
286   gl = query->context->gl_vtable;
287 
288   gl->EndQuery (query->query_type);
289 }
290 
291 /**
292  * gst_gl_query_counter:
293  * @query: a #GstGLQuery
294  *
295  * Record the result of a counter
296  *
297  * Since: 1.10
298  */
299 void
gst_gl_query_counter(GstGLQuery * query)300 gst_gl_query_counter (GstGLQuery * query)
301 {
302   const GstGLFuncs *gl;
303 
304   g_return_if_fail (query != NULL);
305   g_return_if_fail (_query_type_supports_counter (query->query_type));
306 
307   if (!query->supported)
308     return;
309 
310   GST_TRACE ("%p query counter type \'%s\' id %u", query,
311       _query_type_to_string (query->query_type), query->query_id);
312 
313   gst_gl_async_debug_output_log_msg (&query->debug);
314 
315   gl = query->context->gl_vtable;
316   gl->QueryCounter (query->query_id, query->query_type);
317 }
318 
319 /**
320  * gst_gl_query_result:
321  * @query: a #GstGLQuery
322  *
323  * Returns: the result of the query
324  *
325  * Since: 1.10
326  */
327 guint64
gst_gl_query_result(GstGLQuery * query)328 gst_gl_query_result (GstGLQuery * query)
329 {
330   const GstGLFuncs *gl;
331   guint64 ret;
332 
333   g_return_val_if_fail (query != NULL, 0);
334   g_return_val_if_fail (!query->start_called, 0);
335 
336   if (!query->supported)
337     return 0;
338 
339   gl = query->context->gl_vtable;
340   if (gl->GetQueryObjectui64v) {
341     GLuint64 tmp = 0;
342     gl->GetQueryObjectui64v (query->query_id, GL_QUERY_RESULT, &tmp);
343     ret = tmp;
344   } else {
345     guint tmp = 0;
346     gl->GetQueryObjectuiv (query->query_id, GL_QUERY_RESULT, &tmp);
347     ret = tmp;
348   }
349 
350   GST_TRACE ("%p get result %" G_GUINT64_FORMAT " type \'%s\' id %u", query,
351       ret, _query_type_to_string (query->query_type), query->query_id);
352 
353   return ret;
354 }
355