Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; 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 "WebGL2Context.h"
7 : #include "GLContext.h"
8 : #include "WebGLQuery.h"
9 : #include "gfxPrefs.h"
10 : #include "nsThreadUtils.h"
11 :
12 : namespace mozilla {
13 :
14 : /*
15 : * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with
16 : * SAMPLES_PASSED on desktop.
17 : *
18 : * OpenGL ES 3.0 spec 4.1.6:
19 : * If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an
20 : * implementation may choose to use a less precise version of the test which
21 : * can additionally set the samples-boolean state to TRUE in some other
22 : * implementation-dependent cases.
23 : */
24 :
25 : WebGLRefPtr<WebGLQuery>*
26 0 : WebGLContext::ValidateQuerySlotByTarget(const char* funcName, GLenum target)
27 : {
28 0 : if (IsWebGL2()) {
29 0 : switch (target) {
30 : case LOCAL_GL_ANY_SAMPLES_PASSED:
31 : case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
32 0 : return &mQuerySlot_SamplesPassed;
33 :
34 : case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
35 0 : return &mQuerySlot_TFPrimsWritten;
36 :
37 : default:
38 0 : break;
39 : }
40 : }
41 :
42 0 : if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
43 0 : switch (target) {
44 : case LOCAL_GL_TIME_ELAPSED_EXT:
45 0 : return &mQuerySlot_TimeElapsed;
46 :
47 : default:
48 0 : break;
49 : }
50 : }
51 :
52 0 : ErrorInvalidEnum("%s: Bad `target`.", funcName);
53 0 : return nullptr;
54 : }
55 :
56 :
57 : // -------------------------------------------------------------------------
58 : // Query Objects
59 :
60 : already_AddRefed<WebGLQuery>
61 0 : WebGLContext::CreateQuery(const char* funcName)
62 : {
63 0 : if (!funcName) {
64 0 : funcName = "createQuery";
65 : }
66 :
67 0 : if (IsContextLost())
68 0 : return nullptr;
69 :
70 0 : RefPtr<WebGLQuery> globj = new WebGLQuery(this);
71 0 : return globj.forget();
72 : }
73 :
74 : void
75 0 : WebGLContext::DeleteQuery(WebGLQuery* query, const char* funcName)
76 : {
77 0 : if (!funcName) {
78 0 : funcName = "deleteQuery";
79 : }
80 :
81 0 : if (!ValidateDeleteObject(funcName, query))
82 0 : return;
83 :
84 0 : query->DeleteQuery();
85 : }
86 :
87 : bool
88 0 : WebGLContext::IsQuery(const WebGLQuery* query, const char* funcName)
89 : {
90 0 : if (!funcName) {
91 0 : funcName = "isQuery";
92 : }
93 :
94 0 : if (!ValidateIsObject(funcName, query))
95 0 : return false;
96 :
97 0 : return query->IsQuery();
98 : }
99 :
100 : void
101 0 : WebGLContext::BeginQuery(GLenum target, WebGLQuery& query, const char* funcName)
102 : {
103 0 : if (!funcName) {
104 0 : funcName = "beginQuery";
105 : }
106 :
107 0 : if (IsContextLost())
108 0 : return;
109 :
110 0 : if (!ValidateObject(funcName, query))
111 0 : return;
112 :
113 0 : const auto& slot = ValidateQuerySlotByTarget(funcName, target);
114 0 : if (!slot)
115 0 : return;
116 :
117 0 : if (*slot)
118 0 : return ErrorInvalidOperation("%s: Query target already active.", funcName);
119 :
120 : ////
121 :
122 0 : query.BeginQuery(target, *slot);
123 : }
124 :
125 : void
126 0 : WebGLContext::EndQuery(GLenum target, const char* funcName)
127 : {
128 0 : if (!funcName) {
129 0 : funcName = "endQuery";
130 : }
131 :
132 0 : if (IsContextLost())
133 0 : return;
134 :
135 0 : const auto& slot = ValidateQuerySlotByTarget(funcName, target);
136 0 : if (!slot)
137 0 : return;
138 :
139 0 : const auto& query = *slot;
140 0 : if (!query)
141 0 : return ErrorInvalidOperation("%s: Query target not active.", funcName);
142 :
143 0 : query->EndQuery();
144 : }
145 :
146 : void
147 0 : WebGLContext::GetQuery(JSContext* cx, GLenum target, GLenum pname,
148 : JS::MutableHandleValue retval, const char* funcName)
149 : {
150 0 : if (!funcName) {
151 0 : funcName = "getQuery";
152 : }
153 :
154 0 : retval.setNull();
155 0 : if (IsContextLost())
156 0 : return;
157 :
158 0 : switch (pname) {
159 : case LOCAL_GL_CURRENT_QUERY_EXT:
160 : {
161 0 : if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query) &&
162 : target == LOCAL_GL_TIMESTAMP)
163 : {
164 : // Doesn't seem illegal to ask about, but is always null.
165 : // TIMESTAMP has no slot, so ValidateQuerySlotByTarget would generate
166 : // INVALID_ENUM.
167 0 : return;
168 : }
169 :
170 0 : const auto& slot = ValidateQuerySlotByTarget(funcName, target);
171 0 : if (!slot || !*slot)
172 0 : return;
173 :
174 0 : const auto& query = *slot;
175 0 : if (target != query->Target())
176 0 : return;
177 :
178 0 : JS::Rooted<JS::Value> v(cx);
179 0 : dom::GetOrCreateDOMReflector(cx, slot->get(), &v);
180 0 : retval.set(v);
181 : }
182 0 : return;
183 :
184 : case LOCAL_GL_QUERY_COUNTER_BITS_EXT:
185 0 : if (!IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query))
186 0 : break;
187 :
188 0 : if (target != LOCAL_GL_TIME_ELAPSED_EXT &&
189 : target != LOCAL_GL_TIMESTAMP_EXT)
190 : {
191 0 : ErrorInvalidEnum("%s: Bad pname for target.", funcName);
192 0 : return;
193 : }
194 :
195 : {
196 0 : GLint bits = 0;
197 0 : gl->fGetQueryiv(target, pname, &bits);
198 :
199 0 : if (!Has64BitTimestamps() && bits > 32) {
200 0 : bits = 32;
201 : }
202 0 : retval.set(JS::Int32Value(bits));
203 : }
204 0 : return;
205 :
206 : default:
207 0 : break;
208 : }
209 :
210 0 : ErrorInvalidEnum("%s: Bad pname.", funcName);
211 0 : return;
212 : }
213 :
214 : void
215 0 : WebGLContext::GetQueryParameter(JSContext*, const WebGLQuery& query, GLenum pname,
216 : JS::MutableHandleValue retval, const char* funcName)
217 : {
218 0 : if (!funcName) {
219 0 : funcName = "getQueryParameter";
220 : }
221 :
222 0 : retval.setNull();
223 0 : if (IsContextLost())
224 0 : return;
225 :
226 0 : if (!ValidateObject(funcName, query))
227 0 : return;
228 :
229 0 : query.GetQueryParameter(pname, retval);
230 : }
231 :
232 : } // namespace mozilla
|