WebGLQuery.cpp (3778B)
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/. */ 5 6 #include "WebGLQuery.h" 7 8 #include "GLContext.h" 9 #include "WebGLContext.h" 10 #include "mozilla/StaticPrefs_webgl.h" 11 #include "mozilla/dom/WebGL2RenderingContextBinding.h" 12 #include "nsContentUtils.h" 13 14 namespace mozilla { 15 16 //// 17 18 static GLuint GenQuery(gl::GLContext* gl) { 19 GLuint ret = 0; 20 gl->fGenQueries(1, &ret); 21 return ret; 22 } 23 24 WebGLQuery::WebGLQuery(WebGLContext* webgl) 25 : WebGLContextBoundObject(webgl), 26 mGLName(GenQuery(mContext->gl)), 27 mTarget(0), 28 mActiveSlot(nullptr) {} 29 30 WebGLQuery::~WebGLQuery() { 31 if (!mContext) return; 32 mContext->gl->fDeleteQueries(1, &mGLName); 33 } 34 35 //// 36 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; 42 43 default: 44 return target; 45 } 46 47 if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) return target; 48 49 if (gl->IsSupported(gl::GLFeature::occlusion_query2)) 50 return LOCAL_GL_ANY_SAMPLES_PASSED; 51 52 return LOCAL_GL_SAMPLES_PASSED; 53 } 54 55 void WebGLQuery::BeginQuery(GLenum target, RefPtr<WebGLQuery>& slot) { 56 mTarget = target; 57 mActiveSlot = &slot; 58 *mActiveSlot = this; 59 60 //// 61 62 const auto& gl = mContext->gl; 63 64 const auto driverTarget = TargetForDriver(gl, mTarget); 65 gl->fBeginQuery(driverTarget, mGLName); 66 } 67 68 void WebGLQuery::EndQuery() { 69 *mActiveSlot = nullptr; 70 mActiveSlot = nullptr; 71 mCanBeAvailable = false; 72 73 //// 74 75 const auto& gl = mContext->gl; 76 77 const auto driverTarget = TargetForDriver(gl, mTarget); 78 gl->fEndQuery(driverTarget); 79 } 80 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; 86 87 default: 88 mContext->ErrorInvalidEnumInfo("pname", pname); 89 return Nothing(); 90 } 91 92 if (!mTarget) { 93 mContext->ErrorInvalidOperation("Query has never been active."); 94 return Nothing(); 95 } 96 97 if (mActiveSlot) { 98 mContext->ErrorInvalidOperation("Query is still active."); 99 return Nothing(); 100 } 101 102 // End of validation 103 //// 104 105 const auto& gl = mContext->gl; 106 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)); 112 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; 120 } 121 [[fallthrough]]; 122 123 default: 124 gl->fGetQueryObjectuiv(mGLName, LOCAL_GL_QUERY_RESULT, (GLuint*)&val); 125 break; 126 } 127 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); 135 } 136 MOZ_CRASH("Bad `mTarget`."); 137 138 default: 139 MOZ_CRASH("Bad `pname`."); 140 } 141 } 142 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; 148 } 149 150 mTarget = target; 151 mCanBeAvailable = false; 152 153 const auto& gl = mContext->gl; 154 gl->fQueryCounter(mGLName, mTarget); 155 } 156 157 } // namespace mozilla