Bug 1729395 - Handle message sender going away during message processing r=robwu
[gecko.git] / dom / canvas / WebGLQuery.cpp
blob5290d69a500555e51853e28d498397acb6151b54
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
6 #include "WebGLQuery.h"
8 #include "GLContext.h"
9 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
10 #include "mozilla/StaticPrefs_webgl.h"
11 #include "nsContentUtils.h"
12 #include "WebGLContext.h"
14 namespace mozilla {
16 ////
18 static GLuint GenQuery(gl::GLContext* gl) {
19 GLuint ret = 0;
20 gl->fGenQueries(1, &ret);
21 return ret;
24 WebGLQuery::WebGLQuery(WebGLContext* webgl)
25 : WebGLContextBoundObject(webgl),
26 mGLName(GenQuery(mContext->gl)),
27 mTarget(0),
28 mActiveSlot(nullptr) {}
30 WebGLQuery::~WebGLQuery() {
31 if (!mContext) return;
32 mContext->gl->fDeleteQueries(1, &mGLName);
35 ////
37 static GLenum TargetForDriver(const gl::GLContext* gl, GLenum target) {
38 switch (target) {
39 case LOCAL_GL_ANY_SAMPLES_PASSED:
40 case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
41 break;
43 default:
44 return target;
47 if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) return target;
49 if (gl->IsSupported(gl::GLFeature::occlusion_query2))
50 return LOCAL_GL_ANY_SAMPLES_PASSED;
52 return LOCAL_GL_SAMPLES_PASSED;
55 void WebGLQuery::BeginQuery(GLenum target, RefPtr<WebGLQuery>& slot) {
56 mTarget = target;
57 mActiveSlot = &slot;
58 *mActiveSlot = this;
60 ////
62 const auto& gl = mContext->gl;
64 const auto driverTarget = TargetForDriver(gl, mTarget);
65 gl->fBeginQuery(driverTarget, mGLName);
68 void WebGLQuery::EndQuery() {
69 *mActiveSlot = nullptr;
70 mActiveSlot = nullptr;
71 mCanBeAvailable = false;
73 ////
75 const auto& gl = mContext->gl;
77 const auto driverTarget = TargetForDriver(gl, mTarget);
78 gl->fEndQuery(driverTarget);
81 Maybe<double> WebGLQuery::GetQueryParameter(GLenum pname) const {
82 switch (pname) {
83 case LOCAL_GL_QUERY_RESULT_AVAILABLE:
84 case LOCAL_GL_QUERY_RESULT:
85 break;
87 default:
88 mContext->ErrorInvalidEnumInfo("pname", pname);
89 return Nothing();
92 if (!mTarget) {
93 mContext->ErrorInvalidOperation("Query has never been active.");
94 return Nothing();
97 if (mActiveSlot) {
98 mContext->ErrorInvalidOperation("Query is still active.");
99 return Nothing();
102 // End of validation
103 ////
105 const auto& gl = mContext->gl;
107 uint64_t val = 0;
108 switch (pname) {
109 case LOCAL_GL_QUERY_RESULT_AVAILABLE:
110 gl->fGetQueryObjectuiv(mGLName, pname, (GLuint*)&val);
111 return Some(static_cast<bool>(val));
113 case LOCAL_GL_QUERY_RESULT:
114 switch (mTarget) {
115 case LOCAL_GL_TIME_ELAPSED_EXT:
116 case LOCAL_GL_TIMESTAMP_EXT:
117 if (mContext->Has64BitTimestamps()) {
118 gl->fGetQueryObjectui64v(mGLName, pname, &val);
119 break;
121 [[fallthrough]];
123 default:
124 gl->fGetQueryObjectuiv(mGLName, LOCAL_GL_QUERY_RESULT, (GLuint*)&val);
125 break;
128 switch (mTarget) {
129 case LOCAL_GL_ANY_SAMPLES_PASSED:
130 case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
131 case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
132 case LOCAL_GL_TIME_ELAPSED_EXT:
133 case LOCAL_GL_TIMESTAMP_EXT:
134 return Some(val);
136 MOZ_CRASH("Bad `mTarget`.");
138 default:
139 MOZ_CRASH("Bad `pname`.");
143 void WebGLQuery::QueryCounter() {
144 const GLenum target = LOCAL_GL_TIMESTAMP_EXT;
145 if (mTarget && target != mTarget) {
146 mContext->ErrorInvalidOperation("Queries cannot change targets.");
147 return;
150 mTarget = target;
151 mCanBeAvailable = false;
153 const auto& gl = mContext->gl;
154 gl->fQueryCounter(mGLName, mTarget);
157 } // namespace mozilla