content/canvas/src/WebGLContextAsyncQueries.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "WebGLContext.h"
michael@0 7 #include "WebGLQuery.h"
michael@0 8 #include "GLContext.h"
michael@0 9
michael@0 10 using namespace mozilla;
michael@0 11
michael@0 12 /*
michael@0 13 * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with
michael@0 14 * SAMPLES_PASSED on desktop.
michael@0 15 *
michael@0 16 * OpenGL ES 3.0 spec 4.1.6
michael@0 17 * If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an implementation
michael@0 18 * may choose to use a less precise version of the test which can additionally set
michael@0 19 * the samples-boolean state to TRUE in some other implementation-dependent cases.
michael@0 20 */
michael@0 21
michael@0 22 static const char*
michael@0 23 GetQueryTargetEnumString(GLenum target)
michael@0 24 {
michael@0 25 switch (target)
michael@0 26 {
michael@0 27 case LOCAL_GL_ANY_SAMPLES_PASSED:
michael@0 28 return "ANY_SAMPLES_PASSED";
michael@0 29 case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
michael@0 30 return "ANY_SAMPLES_PASSED_CONSERVATIVE";
michael@0 31 case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
michael@0 32 return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
michael@0 33 default:
michael@0 34 break;
michael@0 35 }
michael@0 36
michael@0 37 MOZ_ASSERT(false, "Unknown query `target`.");
michael@0 38 return "UNKNOWN_QUERY_TARGET";
michael@0 39 }
michael@0 40
michael@0 41 static inline GLenum
michael@0 42 SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target)
michael@0 43 {
michael@0 44 MOZ_ASSERT(target == LOCAL_GL_ANY_SAMPLES_PASSED ||
michael@0 45 target == LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
michael@0 46 "unknown occlusion query target");
michael@0 47
michael@0 48 if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) {
michael@0 49 return target;
michael@0 50 } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) {
michael@0 51 return LOCAL_GL_ANY_SAMPLES_PASSED;
michael@0 52 }
michael@0 53
michael@0 54 return LOCAL_GL_SAMPLES_PASSED;
michael@0 55 }
michael@0 56
michael@0 57 already_AddRefed<WebGLQuery>
michael@0 58 WebGLContext::CreateQuery()
michael@0 59 {
michael@0 60 if (IsContextLost())
michael@0 61 return nullptr;
michael@0 62
michael@0 63 if (mActiveOcclusionQuery && !gl->IsGLES()) {
michael@0 64 /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
michael@0 65 * Calling either GenQueriesARB or DeleteQueriesARB while any query of
michael@0 66 * any target is active causes an INVALID_OPERATION error to be
michael@0 67 * generated.
michael@0 68 */
michael@0 69 GenerateWarning("createQuery: the WebGL 2 prototype might generate INVALID_OPERATION"
michael@0 70 "when creating a query object while one other is active.");
michael@0 71 /*
michael@0 72 * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a good
michael@0 73 * mechanism to do this yet. See bug 898404.
michael@0 74 */
michael@0 75 }
michael@0 76
michael@0 77 nsRefPtr<WebGLQuery> globj = new WebGLQuery(this);
michael@0 78
michael@0 79 return globj.forget();
michael@0 80 }
michael@0 81
michael@0 82 void
michael@0 83 WebGLContext::DeleteQuery(WebGLQuery *query)
michael@0 84 {
michael@0 85 if (IsContextLost())
michael@0 86 return;
michael@0 87
michael@0 88 if (!query)
michael@0 89 return;
michael@0 90
michael@0 91 if (query->IsDeleted())
michael@0 92 return;
michael@0 93
michael@0 94 if (query->IsActive()) {
michael@0 95 EndQuery(query->mType);
michael@0 96 }
michael@0 97
michael@0 98 if (mActiveOcclusionQuery && !gl->IsGLES()) {
michael@0 99 /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
michael@0 100 * Calling either GenQueriesARB or DeleteQueriesARB while any query of
michael@0 101 * any target is active causes an INVALID_OPERATION error to be
michael@0 102 * generated.
michael@0 103 */
michael@0 104 GenerateWarning("deleteQuery: the WebGL 2 prototype might generate INVALID_OPERATION"
michael@0 105 "when deleting a query object while one other is active.");
michael@0 106 }
michael@0 107
michael@0 108 query->RequestDelete();
michael@0 109 }
michael@0 110
michael@0 111 void
michael@0 112 WebGLContext::BeginQuery(GLenum target, WebGLQuery *query)
michael@0 113 {
michael@0 114 if (IsContextLost())
michael@0 115 return;
michael@0 116
michael@0 117 WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "beginQuery");
michael@0 118 if (!targetSlot) {
michael@0 119 return;
michael@0 120 }
michael@0 121
michael@0 122 if (!query) {
michael@0 123 /* SPECS BeginQuery.1
michael@0 124 * http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
michael@0 125 * BeginQueryEXT sets the active query object name for the query type given
michael@0 126 * by <target> to <id>. If BeginQueryEXT is called with an <id> of zero, if
michael@0 127 * the active query object name for <target> is non-zero (for the targets
michael@0 128 * ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the
michael@0 129 * active query for either target is non-zero), if <id> is the name of an
michael@0 130 * existing query object whose type does not match <target>, or if <id> is the
michael@0 131 * active query object name for any query type, the error INVALID_OPERATION is
michael@0 132 * generated.
michael@0 133 */
michael@0 134 ErrorInvalidOperation("beginQuery: query should not be null");
michael@0 135 return;
michael@0 136 }
michael@0 137
michael@0 138 if (query->IsDeleted()) {
michael@0 139 /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
michael@0 140 * BeginQueryEXT fails and an INVALID_OPERATION error is generated if <id>
michael@0 141 * is not a name returned from a previous call to GenQueriesEXT, or if such
michael@0 142 * a name has since been deleted with DeleteQueriesEXT.
michael@0 143 */
michael@0 144 ErrorInvalidOperation("beginQuery: query has been deleted");
michael@0 145 return;
michael@0 146 }
michael@0 147
michael@0 148 if (query->HasEverBeenActive() &&
michael@0 149 query->mType != target)
michael@0 150 {
michael@0 151 /*
michael@0 152 * See SPECS BeginQuery.1
michael@0 153 */
michael@0 154 ErrorInvalidOperation("beginQuery: target doesn't match with the query type");
michael@0 155 return;
michael@0 156 }
michael@0 157
michael@0 158 if (*targetSlot) {
michael@0 159 /*
michael@0 160 * See SPECS BeginQuery.1
michael@0 161 */
michael@0 162 ErrorInvalidOperation("beginQuery: an other query already active");
michael@0 163 return;
michael@0 164 }
michael@0 165
michael@0 166 if (!query->HasEverBeenActive()) {
michael@0 167 query->mType = target;
michael@0 168 }
michael@0 169
michael@0 170 MakeContextCurrent();
michael@0 171
michael@0 172 if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
michael@0 173 gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->mGLName);
michael@0 174 } else {
michael@0 175 gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName);
michael@0 176 }
michael@0 177
michael@0 178 *targetSlot = query;
michael@0 179 }
michael@0 180
michael@0 181 void
michael@0 182 WebGLContext::EndQuery(GLenum target)
michael@0 183 {
michael@0 184 if (IsContextLost())
michael@0 185 return;
michael@0 186
michael@0 187 WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "endQuery");
michael@0 188 if (!targetSlot) {
michael@0 189 return;
michael@0 190 }
michael@0 191
michael@0 192 if (!*targetSlot ||
michael@0 193 target != (*targetSlot)->mType)
michael@0 194 {
michael@0 195 /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
michael@0 196 * marks the end of the sequence of commands to be tracked for the query type
michael@0 197 * given by <target>. The active query object for <target> is updated to
michael@0 198 * indicate that query results are not available, and the active query object
michael@0 199 * name for <target> is reset to zero. When the commands issued prior to
michael@0 200 * EndQueryEXT have completed and a final query result is available, the
michael@0 201 * query object active when EndQueryEXT is called is updated by the GL. The
michael@0 202 * query object is updated to indicate that the query results are available
michael@0 203 * and to contain the query result. If the active query object name for
michael@0 204 * <target> is zero when EndQueryEXT is called, the error INVALID_OPERATION
michael@0 205 * is generated.
michael@0 206 */
michael@0 207 ErrorInvalidOperation("endQuery: There is no active query of type %s.",
michael@0 208 GetQueryTargetEnumString(target));
michael@0 209 return;
michael@0 210 }
michael@0 211
michael@0 212 MakeContextCurrent();
michael@0 213
michael@0 214 if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
michael@0 215 gl->fEndQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
michael@0 216 } else {
michael@0 217 gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target));
michael@0 218 }
michael@0 219
michael@0 220 *targetSlot = nullptr;
michael@0 221 }
michael@0 222
michael@0 223 bool
michael@0 224 WebGLContext::IsQuery(WebGLQuery *query)
michael@0 225 {
michael@0 226 if (IsContextLost())
michael@0 227 return false;
michael@0 228
michael@0 229 if (!query)
michael@0 230 return false;
michael@0 231
michael@0 232 return ValidateObjectAllowDeleted("isQuery", query) &&
michael@0 233 !query->IsDeleted() &&
michael@0 234 query->HasEverBeenActive();
michael@0 235 }
michael@0 236
michael@0 237 already_AddRefed<WebGLQuery>
michael@0 238 WebGLContext::GetQuery(GLenum target, GLenum pname)
michael@0 239 {
michael@0 240 if (IsContextLost())
michael@0 241 return nullptr;
michael@0 242
michael@0 243 WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "getQuery");
michael@0 244 if (!targetSlot) {
michael@0 245 return nullptr;
michael@0 246 }
michael@0 247
michael@0 248 if (pname != LOCAL_GL_CURRENT_QUERY) {
michael@0 249 /* OpenGL ES 3.0 spec 6.1.7
michael@0 250 * pname must be CURRENT_QUERY.
michael@0 251 */
michael@0 252 ErrorInvalidEnum("getQuery: pname must be CURRENT_QUERY");
michael@0 253 return nullptr;
michael@0 254 }
michael@0 255
michael@0 256 nsRefPtr<WebGLQuery> tmp = targetSlot->get();
michael@0 257 return tmp.forget();
michael@0 258 }
michael@0 259
michael@0 260 JS::Value
michael@0 261 WebGLContext::GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname)
michael@0 262 {
michael@0 263 if (IsContextLost())
michael@0 264 return JS::NullValue();
michael@0 265
michael@0 266 if (!query) {
michael@0 267 /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1)
michael@0 268 * If id is not the name of a query object, or if the query object named by id is
michael@0 269 * currently active, then an INVALID_OPERATION error is generated. pname must be
michael@0 270 * QUERY_RESULT or QUERY_RESULT_AVAILABLE.
michael@0 271 */
michael@0 272 ErrorInvalidOperation("getQueryObject: query should not be null");
michael@0 273 return JS::NullValue();
michael@0 274 }
michael@0 275
michael@0 276 if (query->IsDeleted()) {
michael@0 277 // See (spec getQueryObject 1)
michael@0 278 ErrorInvalidOperation("getQueryObject: query has been deleted");
michael@0 279 return JS::NullValue();
michael@0 280 }
michael@0 281
michael@0 282 if (query->IsActive()) {
michael@0 283 // See (spec getQueryObject 1)
michael@0 284 ErrorInvalidOperation("getQueryObject: query is active");
michael@0 285 return JS::NullValue();
michael@0 286 }
michael@0 287
michael@0 288 if (!query->HasEverBeenActive()) {
michael@0 289 /* See (spec getQueryObject 1)
michael@0 290 * If this instance of WebGLQuery has never been active before, that mean that
michael@0 291 * query->mGLName is not a query object yet.
michael@0 292 */
michael@0 293 ErrorInvalidOperation("getQueryObject: query has never been active");
michael@0 294 return JS::NullValue();
michael@0 295 }
michael@0 296
michael@0 297 switch (pname)
michael@0 298 {
michael@0 299 case LOCAL_GL_QUERY_RESULT_AVAILABLE:
michael@0 300 {
michael@0 301 GLuint returned = 0;
michael@0 302
michael@0 303 MakeContextCurrent();
michael@0 304 gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);
michael@0 305
michael@0 306 return JS::BooleanValue(returned != 0);
michael@0 307 }
michael@0 308
michael@0 309 case LOCAL_GL_QUERY_RESULT:
michael@0 310 {
michael@0 311 GLuint returned = 0;
michael@0 312
michael@0 313 MakeContextCurrent();
michael@0 314 gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT, &returned);
michael@0 315
michael@0 316 if (query->mType == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
michael@0 317 return JS::NumberValue(uint32_t(returned));
michael@0 318 }
michael@0 319
michael@0 320 /*
michael@0 321 * test (returned != 0) is important because ARB_occlusion_query on desktop drivers
michael@0 322 * return the number of samples drawed when the OpenGL ES extension
michael@0 323 * ARB_occlusion_query_boolean return only a boolean if a sample has been drawed.
michael@0 324 */
michael@0 325 return JS::BooleanValue(returned != 0);
michael@0 326 }
michael@0 327
michael@0 328 default:
michael@0 329 break;
michael@0 330 }
michael@0 331
michael@0 332 ErrorInvalidEnum("getQueryObject: pname must be QUERY_RESULT{_AVAILABLE}");
michael@0 333 return JS::NullValue();
michael@0 334 }
michael@0 335
michael@0 336 WebGLRefPtr<WebGLQuery>*
michael@0 337 WebGLContext::GetQueryTargetSlot(GLenum target, const char* infos)
michael@0 338 {
michael@0 339 switch (target) {
michael@0 340 case LOCAL_GL_ANY_SAMPLES_PASSED:
michael@0 341 case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
michael@0 342 return &mActiveOcclusionQuery;
michael@0 343 case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
michael@0 344 return &mActiveTransformFeedbackQuery;
michael@0 345 }
michael@0 346
michael@0 347 ErrorInvalidEnum("%s: unknown query target", infos);
michael@0 348 return nullptr;
michael@0 349 }
michael@0 350
michael@0 351

mercurial