1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "ContextStateTracker.h"
7 #include "GLContext.h"
8 #ifdef MOZ_ENABLE_PROFILER_SPS
9 #include "ProfilerMarkers.h"
10 #endif
11
12 namespace mozilla {
13
14 void
PushOGLSection(GLContext * aGL,const char * aSectionName)15 ContextStateTrackerOGL::PushOGLSection(GLContext* aGL, const char* aSectionName)
16 {
17 if (!profiler_feature_active("gpu")) {
18 return;
19 }
20
21 if (!aGL->IsSupported(gl::GLFeature::query_objects)) {
22 return;
23 }
24
25 if (mSectionStack.Length() > 0) {
26 // We need to end the query since we're starting a new section and restore it
27 // when this section is finished.
28 aGL->fEndQuery(LOCAL_GL_TIME_ELAPSED);
29 Top().mCpuTimeEnd = TimeStamp::Now();
30 }
31
32 ContextState newSection(aSectionName);
33
34 GLuint queryObject;
35 aGL->fGenQueries(1, &queryObject);
36 newSection.mStartQueryHandle = queryObject;
37 newSection.mCpuTimeStart = TimeStamp::Now();
38
39 aGL->fBeginQuery(LOCAL_GL_TIME_ELAPSED_EXT, queryObject);
40
41 mSectionStack.AppendElement(newSection);
42 }
43
44 void
PopOGLSection(GLContext * aGL,const char * aSectionName)45 ContextStateTrackerOGL::PopOGLSection(GLContext* aGL, const char* aSectionName)
46 {
47 // We might have ignored a section start if we started profiling
48 // in the middle section. If so we will ignore this unmatched end.
49 if (mSectionStack.Length() == 0) {
50 return;
51 }
52
53 int i = mSectionStack.Length() - 1;
54 MOZ_ASSERT(strcmp(mSectionStack[i].mSectionName, aSectionName) == 0);
55 aGL->fEndQuery(LOCAL_GL_TIME_ELAPSED);
56 mSectionStack[i].mCpuTimeEnd = TimeStamp::Now();
57 mCompletedSections.AppendElement(mSectionStack[i]);
58 mSectionStack.RemoveElementAt(i);
59
60 if (i - 1 >= 0) {
61 const char* sectionToRestore = Top().mSectionName;
62
63 // We need to restore the outer section
64 // Well do this by completing this section and adding a new
65 // one with the same name
66 mCompletedSections.AppendElement(Top());
67 mSectionStack.RemoveElementAt(i - 1);
68
69 ContextState newSection(sectionToRestore);
70
71 GLuint queryObject;
72 aGL->fGenQueries(1, &queryObject);
73 newSection.mStartQueryHandle = queryObject;
74 newSection.mCpuTimeStart = TimeStamp::Now();
75
76 aGL->fBeginQuery(LOCAL_GL_TIME_ELAPSED_EXT, queryObject);
77
78 mSectionStack.AppendElement(newSection);
79 }
80
81 Flush(aGL);
82 }
83
84 void
Flush(GLContext * aGL)85 ContextStateTrackerOGL::Flush(GLContext* aGL)
86 {
87 TimeStamp now = TimeStamp::Now();
88
89 while (mCompletedSections.Length() != 0) {
90 // On mac we see QUERY_RESULT_AVAILABLE cause a GL flush if we query it
91 // too early. For profiling we rather have the last 200ms of data missing
92 // while causing let's measurement distortions.
93 if (mCompletedSections[0].mCpuTimeEnd + TimeDuration::FromMilliseconds(200) > now) {
94 break;
95 }
96
97 GLuint handle = mCompletedSections[0].mStartQueryHandle;
98
99 // We've waiting 200ms, content rendering at > 20 FPS will be ready. We
100 // shouldn't see any flushes now.
101 GLuint returned = 0;
102 aGL->fGetQueryObjectuiv(handle, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);
103
104 if (!returned) {
105 break;
106 }
107
108 GLuint gpuTime = 0;
109 aGL->fGetQueryObjectuiv(handle, LOCAL_GL_QUERY_RESULT, &gpuTime);
110
111 aGL->fDeleteQueries(1, &handle);
112
113 #ifdef MOZ_ENABLE_PROFILER_SPS
114 PROFILER_MARKER_PAYLOAD("gpu_timer_query", new GPUMarkerPayload(
115 mCompletedSections[0].mCpuTimeStart,
116 mCompletedSections[0].mCpuTimeEnd,
117 0,
118 gpuTime
119 ));
120 #endif
121
122 mCompletedSections.RemoveElementAt(0);
123 }
124 }
125
126 void
DestroyOGL(GLContext * aGL)127 ContextStateTrackerOGL::DestroyOGL(GLContext* aGL)
128 {
129 while (mCompletedSections.Length() != 0) {
130 GLuint handle = (GLuint)mCompletedSections[0].mStartQueryHandle;
131 aGL->fDeleteQueries(1, &handle);
132 mCompletedSections.RemoveElementAt(0);
133 }
134 }
135
136 } // namespace mozilla
137
138