Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/canvas/WebGLQuery.cpp
Line
Count
Source (jump to first uncovered line)
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 "WebGLQuery.h"
7
8
#include "gfxPrefs.h"
9
#include "GLContext.h"
10
#include "mozilla/dom/WebGL2RenderingContextBinding.h"
11
#include "nsContentUtils.h"
12
#include "WebGLContext.h"
13
14
namespace mozilla {
15
16
////
17
18
static GLuint
19
GenQuery(gl::GLContext* gl)
20
0
{
21
0
    GLuint ret = 0;
22
0
    gl->fGenQueries(1, &ret);
23
0
    return ret;
24
0
}
25
26
WebGLQuery::WebGLQuery(WebGLContext* webgl)
27
    : WebGLRefCountedObject(webgl)
28
    , mGLName(GenQuery(mContext->gl))
29
    , mTarget(0)
30
    , mActiveSlot(nullptr)
31
0
{
32
0
    mContext->mQueries.insertBack(this);
33
0
}
34
35
void
36
WebGLQuery::Delete()
37
0
{
38
0
    mContext->gl->fDeleteQueries(1, &mGLName);
39
0
    LinkedListElement<WebGLQuery>::removeFrom(mContext->mQueries);
40
0
}
41
42
////
43
44
static GLenum
45
TargetForDriver(const gl::GLContext* gl, GLenum target)
46
0
{
47
0
    switch (target) {
48
0
    case LOCAL_GL_ANY_SAMPLES_PASSED:
49
0
    case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
50
0
        break;
51
0
52
0
    default:
53
0
        return target;
54
0
    }
55
0
56
0
    if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean))
57
0
        return target;
58
0
59
0
    if (gl->IsSupported(gl::GLFeature::occlusion_query2))
60
0
        return LOCAL_GL_ANY_SAMPLES_PASSED;
61
0
62
0
    return LOCAL_GL_SAMPLES_PASSED;
63
0
}
64
65
void
66
WebGLQuery::BeginQuery(GLenum target, WebGLRefPtr<WebGLQuery>& slot)
67
0
{
68
0
    if (mTarget && target != mTarget) {
69
0
        mContext->ErrorInvalidOperation("Queries cannot change targets.");
70
0
        return;
71
0
    }
72
0
73
0
    ////
74
0
75
0
    mTarget = target;
76
0
    mActiveSlot = &slot;
77
0
    *mActiveSlot = this;
78
0
79
0
    ////
80
0
81
0
    const auto& gl = mContext->gl;
82
0
83
0
    const auto driverTarget = TargetForDriver(gl, mTarget);
84
0
    gl->fBeginQuery(driverTarget, mGLName);
85
0
}
86
87
void
88
WebGLQuery::EndQuery()
89
0
{
90
0
    *mActiveSlot = nullptr;
91
0
    mActiveSlot = nullptr;
92
0
    mCanBeAvailable = false;
93
0
94
0
    ////
95
0
96
0
    const auto& gl = mContext->gl;
97
0
98
0
    const auto driverTarget = TargetForDriver(gl, mTarget);
99
0
    gl->fEndQuery(driverTarget);
100
0
101
0
    ////
102
0
103
0
    const auto& availRunnable = mContext->EnsureAvailabilityRunnable();
104
0
    availRunnable->mQueries.push_back(this);
105
0
}
106
107
void
108
WebGLQuery::GetQueryParameter(GLenum pname, JS::MutableHandleValue retval) const
109
0
{
110
0
    switch (pname) {
111
0
    case LOCAL_GL_QUERY_RESULT_AVAILABLE:
112
0
    case LOCAL_GL_QUERY_RESULT:
113
0
        break;
114
0
115
0
    default:
116
0
        mContext->ErrorInvalidEnumInfo("pname", pname);
117
0
        return;
118
0
    }
119
0
120
0
    if (!mTarget) {
121
0
        mContext->ErrorInvalidOperation("Query has never been active.");
122
0
        return;
123
0
    }
124
0
125
0
    if (mActiveSlot)
126
0
        return mContext->ErrorInvalidOperation("Query is still active.");
127
0
128
0
    // End of validation
129
0
    ////
130
0
131
0
    // We must usually wait for an event loop before the query can be available.
132
0
    const bool canBeAvailable = (mCanBeAvailable || gfxPrefs::WebGLImmediateQueries());
133
0
    if (!canBeAvailable) {
134
0
        if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
135
0
            retval.set(JS::BooleanValue(false));
136
0
        }
137
0
        return;
138
0
    }
139
0
140
0
    const auto& gl = mContext->gl;
141
0
142
0
    uint64_t val = 0;
143
0
    switch (pname) {
144
0
    case LOCAL_GL_QUERY_RESULT_AVAILABLE:
145
0
        gl->fGetQueryObjectuiv(mGLName, pname, (GLuint*)&val);
146
0
        retval.set(JS::BooleanValue(bool(val)));
147
0
        return;
148
0
149
0
    case LOCAL_GL_QUERY_RESULT:
150
0
        switch (mTarget) {
151
0
        case LOCAL_GL_TIME_ELAPSED_EXT:
152
0
        case LOCAL_GL_TIMESTAMP_EXT:
153
0
            if (mContext->Has64BitTimestamps()) {
154
0
                gl->fGetQueryObjectui64v(mGLName, pname, &val);
155
0
                break;
156
0
            }
157
0
            MOZ_FALLTHROUGH;
158
0
159
0
        default:
160
0
            gl->fGetQueryObjectuiv(mGLName, LOCAL_GL_QUERY_RESULT, (GLuint*)&val);
161
0
            break;
162
0
        }
163
0
164
0
        switch (mTarget) {
165
0
        case LOCAL_GL_ANY_SAMPLES_PASSED:
166
0
        case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
167
0
        case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
168
0
        case LOCAL_GL_TIME_ELAPSED_EXT:
169
0
        case LOCAL_GL_TIMESTAMP_EXT:
170
0
            retval.set(JS::NumberValue(val));
171
0
            break;
172
0
173
0
        default:
174
0
            MOZ_CRASH("Bad `mTarget`.");
175
0
        }
176
0
        return;
177
0
178
0
    default:
179
0
        MOZ_CRASH("Bad `pname`.");
180
0
    }
181
0
}
182
183
bool
184
WebGLQuery::IsQuery() const
185
0
{
186
0
    MOZ_ASSERT(!IsDeleted());
187
0
188
0
    if (!mTarget)
189
0
        return false;
190
0
191
0
    return true;
192
0
}
193
194
void
195
WebGLQuery::DeleteQuery()
196
0
{
197
0
    MOZ_ASSERT(!IsDeleteRequested());
198
0
199
0
    if (mActiveSlot) {
200
0
        EndQuery();
201
0
    }
202
0
203
0
    RequestDelete();
204
0
}
205
206
void
207
WebGLQuery::QueryCounter(GLenum target)
208
0
{
209
0
    if (target != LOCAL_GL_TIMESTAMP_EXT) {
210
0
        mContext->ErrorInvalidEnum("`target` must be TIMESTAMP_EXT.");
211
0
        return;
212
0
    }
213
0
214
0
    if (mTarget && target != mTarget) {
215
0
        mContext->ErrorInvalidOperation("Queries cannot change targets.");
216
0
        return;
217
0
    }
218
0
219
0
    mTarget = target;
220
0
    mCanBeAvailable = false;
221
0
222
0
    const auto& gl = mContext->gl;
223
0
    gl->fQueryCounter(mGLName, mTarget);
224
0
225
0
    const auto& availRunnable = mContext->EnsureAvailabilityRunnable();
226
0
    availRunnable->mQueries.push_back(this);
227
0
}
228
229
////
230
231
JSObject*
232
WebGLQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
233
0
{
234
0
    return dom::WebGLQuery_Binding::Wrap(cx, this, givenProto);
235
0
}
236
237
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLQuery)
238
239
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLQuery, AddRef)
240
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLQuery, Release)
241
242
} // namespace mozilla