--- a/dom/canvas/WebGL1Context.cpp
+++ b/dom/canvas/WebGL1Context.cpp
@@ -33,22 +33,16 @@ WebGL1Context::CreateFormatUsage(gl::GLC
}
JSObject*
WebGL1Context::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLRenderingContextBinding::Wrap(cx, this, givenProto);
}
-bool
-WebGL1Context::ValidateQueryTarget(GLenum target, const char* info)
-{
- return false;
-}
-
} // namespace mozilla
nsresult
NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** out_result)
{
mozilla::Telemetry::Accumulate(mozilla::Telemetry::CANVAS_WEBGL_USED, 1);
nsIDOMWebGLRenderingContext* ctx = mozilla::WebGL1Context::Create();
--- a/dom/canvas/WebGL1Context.h
+++ b/dom/canvas/WebGL1Context.h
@@ -31,15 +31,14 @@ public:
// nsWrapperCache
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
private:
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type,
uint32_t* alignment,
const char* info) override;
- virtual bool ValidateQueryTarget(GLenum target, const char* info) override;
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override;
};
} // namespace mozilla
#endif // WEBGL_1_CONTEXT_H_
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -298,28 +298,16 @@ public:
GLuint srcElemOffset)
{
ClearBufferuiv(buffer, drawBuffer, Uint32Arr::From(list), srcElemOffset);
}
void ClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil);
// -------------------------------------------------------------------------
- // Query Objects - WebGL2ContextQueries.cpp
-
- already_AddRefed<WebGLQuery> CreateQuery();
- void DeleteQuery(WebGLQuery* query);
- bool IsQuery(WebGLQuery* query);
- void BeginQuery(GLenum target, WebGLQuery* query);
- void EndQuery(GLenum target);
- already_AddRefed<WebGLQuery> GetQuery(GLenum target, GLenum pname);
- void GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS::MutableHandleValue retval);
-
-
- // -------------------------------------------------------------------------
// Sampler Objects - WebGL2ContextSamplers.cpp
already_AddRefed<WebGLSampler> CreateSampler();
void DeleteSampler(WebGLSampler* sampler);
bool IsSampler(WebGLSampler* sampler);
void BindSampler(GLuint unit, WebGLSampler* sampler);
void SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param);
void SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Int32Array& param);
@@ -405,15 +393,14 @@ private:
void UpdateBoundQuery(GLenum target, WebGLQuery* query);
// CreateVertexArrayImpl is assumed to be infallible.
virtual WebGLVertexArray* CreateVertexArrayImpl() override;
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type,
uint32_t* alignment,
const char* info) override;
- virtual bool ValidateQueryTarget(GLenum target, const char* info) override;
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override;
};
} // namespace mozilla
#endif
--- a/dom/canvas/WebGL2ContextQueries.cpp
+++ b/dom/canvas/WebGL2ContextQueries.cpp
@@ -17,393 +17,220 @@ namespace mozilla {
*
* OpenGL ES 3.0 spec 4.1.6:
* If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an
* implementation may choose to use a less precise version of the test which
* can additionally set the samples-boolean state to TRUE in some other
* implementation-dependent cases.
*/
-static const char*
-GetQueryTargetEnumString(GLenum target)
+WebGLRefPtr<WebGLQuery>*
+WebGLContext::ValidateQuerySlotByTarget(const char* funcName, GLenum target)
{
- switch (target)
- {
- case LOCAL_GL_ANY_SAMPLES_PASSED:
- return "ANY_SAMPLES_PASSED";
- case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
- return "ANY_SAMPLES_PASSED_CONSERVATIVE";
- case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
- return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
- default:
- break;
+ if (IsWebGL2()) {
+ switch (target) {
+ case LOCAL_GL_ANY_SAMPLES_PASSED:
+ case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return &mQuerySlot_SamplesPassed;
+
+ case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return &mQuerySlot_TFPrimsWritten;
+
+ default:
+ break;
+ }
}
- MOZ_ASSERT(false, "Unknown query `target`.");
- return "UNKNOWN_QUERY_TARGET";
-}
+ if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
+ switch (target) {
+ case LOCAL_GL_TIME_ELAPSED_EXT:
+ return &mQuerySlot_TimeElapsed;
-static inline GLenum
-SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target)
-{
- MOZ_ASSERT(target == LOCAL_GL_ANY_SAMPLES_PASSED ||
- target == LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
- "unknown occlusion query target");
-
- if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) {
- return target;
- } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) {
- return LOCAL_GL_ANY_SAMPLES_PASSED;
+ default:
+ break;
+ }
}
- return LOCAL_GL_SAMPLES_PASSED;
-}
-
-WebGLRefPtr<WebGLQuery>&
-WebGLContext::GetQuerySlotByTarget(GLenum target)
-{
- /* This function assumes that target has been validated for either
- * WebGL1 or WebGL2.
- */
- switch (target) {
- case LOCAL_GL_ANY_SAMPLES_PASSED:
- case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
- return mActiveOcclusionQuery;
-
- case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
- return mActiveTransformFeedbackQuery;
-
- default:
- MOZ_CRASH("GFX: Should not get here.");
- }
+ ErrorInvalidEnum("%s: Bad `target`.", funcName);
+ return nullptr;
}
// -------------------------------------------------------------------------
// Query Objects
already_AddRefed<WebGLQuery>
-WebGL2Context::CreateQuery()
+WebGLContext::CreateQuery(const char* funcName)
{
+ if (!funcName) {
+ funcName = "createQuery";
+ }
+
if (IsContextLost())
return nullptr;
- if (mActiveOcclusionQuery && !gl->IsGLES()) {
- /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
- *
- * Calling either GenQueriesARB or DeleteQueriesARB while any query of
- * any target is active causes an INVALID_OPERATION error to be
- * generated.
- */
- GenerateWarning("createQuery: The WebGL 2 prototype might generate"
- " INVALID_OPERATION when creating a query object while"
- " one other is active.");
- /*
- * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a
- * good mechanism to do this yet. See bug 898404.
- */
- }
-
RefPtr<WebGLQuery> globj = new WebGLQuery(this);
-
return globj.forget();
}
void
-WebGL2Context::DeleteQuery(WebGLQuery* query)
+WebGLContext::DeleteQuery(WebGLQuery* query, const char* funcName)
{
+ if (!funcName) {
+ funcName = "deleteQuery";
+ }
+
if (IsContextLost())
return;
if (!query)
return;
- if (query->IsDeleted())
+ if (!ValidateObjectAllowDeleted(funcName, query))
return;
- if (query->IsActive())
- EndQuery(query->mType);
-
- if (mActiveOcclusionQuery && !gl->IsGLES()) {
- /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
- *
- * Calling either GenQueriesARB or DeleteQueriesARB while any query of
- * any target is active causes an INVALID_OPERATION error to be
- * generated.
- */
- GenerateWarning("deleteQuery: The WebGL 2 prototype might generate"
- " INVALID_OPERATION when deleting a query object while"
- " one other is active.");
- }
-
- query->RequestDelete();
+ query->DeleteQuery();
}
bool
-WebGL2Context::IsQuery(WebGLQuery* query)
+WebGLContext::IsQuery(const WebGLQuery* query, const char* funcName)
{
+ if (!funcName) {
+ funcName = "isQuery";
+ }
+
if (IsContextLost())
return false;
if (!query)
return false;
- return (ValidateObjectAllowDeleted("isQuery", query) &&
- !query->IsDeleted() &&
- query->HasEverBeenActive());
+ if (!ValidateObjectAllowDeleted("isQuery", query))
+ return false;
+
+ return query->IsQuery();
}
void
-WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query)
+WebGLContext::BeginQuery(GLenum target, WebGLQuery* query, const char* funcName)
{
- if (IsContextLost())
- return;
-
- if (!ValidateQueryTarget(target, "beginQuery"))
- return;
-
- if (!query) {
- /* From GLES's EXT_occlusion_query_boolean:
- * BeginQueryEXT sets the active query object name for the query
- * type given by <target> to <id>. If BeginQueryEXT is called with
- * an <id> of zero, if the active query object name for <target> is
- * non-zero (for the targets ANY_SAMPLES_PASSED_EXT and
- * ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the active query for
- * either target is non-zero), if <id> is the name of an existing
- * query object whose type does not match <target>, or if <id> is
- * the active query object name for any query type, the error
- * INVALID_OPERATION is generated.
- */
- ErrorInvalidOperation("beginQuery: Query should not be null.");
- return;
+ if (!funcName) {
+ funcName = "beginQuery";
}
- if (query->IsDeleted()) {
- /* From GLES's EXT_occlusion_query_boolean:
- * BeginQueryEXT fails and an INVALID_OPERATION error is generated
- * if <id> is not a name returned from a previous call to
- * GenQueriesEXT, or if such a name has since been deleted with
- * DeleteQueriesEXT.
- */
- ErrorInvalidOperation("beginQuery: Query has been deleted.");
- return;
- }
-
- if (query->HasEverBeenActive() &&
- query->mType != target)
- {
- ErrorInvalidOperation("beginQuery: Target doesn't match with the query"
- " type.");
- return;
- }
-
- WebGLRefPtr<WebGLQuery>& querySlot = GetQuerySlotByTarget(target);
- WebGLQuery* activeQuery = querySlot.get();
- if (activeQuery)
- return ErrorInvalidOperation("beginQuery: An other query already active.");
-
- if (!query->HasEverBeenActive())
- query->mType = target;
-
- MakeContextCurrent();
-
- if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
- gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
- query->mGLName);
- } else {
- gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target),
- query->mGLName);
- }
-
- UpdateBoundQuery(target, query);
-}
-
-void
-WebGL2Context::EndQuery(GLenum target)
-{
if (IsContextLost())
return;
- if (!ValidateQueryTarget(target, "endQuery"))
+ if (!ValidateObject(funcName, query))
+ return;
+
+ const auto& slot = ValidateQuerySlotByTarget(funcName, target);
+ if (!slot)
return;
- WebGLRefPtr<WebGLQuery>& querySlot = GetQuerySlotByTarget(target);
- WebGLQuery* activeQuery = querySlot.get();
+ if (*slot)
+ return ErrorInvalidOperation("%s: Query target already active.", funcName);
- if (!activeQuery || target != activeQuery->mType)
- {
- /* From GLES's EXT_occlusion_query_boolean:
- * marks the end of the sequence of commands to be tracked for the
- * query type given by <target>. The active query object for
- * <target> is updated to indicate that query results are not
- * available, and the active query object name for <target> is reset
- * to zero. When the commands issued prior to EndQueryEXT have
- * completed and a final query result is available, the query object
- * active when EndQueryEXT is called is updated by the GL. The query
- * object is updated to indicate that the query results are
- * available and to contain the query result. If the active query
- * object name for <target> is zero when EndQueryEXT is called, the
- * error INVALID_OPERATION is generated.
- */
- ErrorInvalidOperation("endQuery: There is no active query of type %s.",
- GetQueryTargetEnumString(target));
- return;
- }
-
- MakeContextCurrent();
-
- if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
- gl->fEndQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
- } else {
- gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target));
- }
-
- UpdateBoundQuery(target, nullptr);
- NS_DispatchToCurrentThread(new WebGLQuery::AvailableRunnable(activeQuery));
-}
+ ////
-already_AddRefed<WebGLQuery>
-WebGL2Context::GetQuery(GLenum target, GLenum pname)
-{
- if (IsContextLost())
- return nullptr;
-
- if (!ValidateQueryTarget(target, "getQuery"))
- return nullptr;
-
- if (pname != LOCAL_GL_CURRENT_QUERY) {
- /* OpenGL ES 3.0 spec 6.1.7:
- * pname must be CURRENT_QUERY.
- */
- ErrorInvalidEnum("getQuery: `pname` must be CURRENT_QUERY.");
- return nullptr;
- }
+ if (!query->BeginQuery(target))
+ return;
- WebGLRefPtr<WebGLQuery>& targetSlot = GetQuerySlotByTarget(target);
- RefPtr<WebGLQuery> tmp = targetSlot.get();
- if (tmp && tmp->mType != target) {
- // Query in slot doesn't match target
- return nullptr;
- }
-
- return tmp.forget();
-}
-
-static bool
-ValidateQueryEnum(WebGLContext* webgl, GLenum pname, const char* info)
-{
- switch (pname) {
- case LOCAL_GL_QUERY_RESULT_AVAILABLE:
- case LOCAL_GL_QUERY_RESULT:
- return true;
-
- default:
- webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
- return false;
- }
+ *slot = query;
}
void
-WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
- JS::MutableHandleValue retval)
+WebGLContext::EndQuery(GLenum target, const char* funcName)
{
- retval.set(JS::NullValue());
+ if (!funcName) {
+ funcName = "endQuery";
+ }
if (IsContextLost())
return;
- if (!ValidateQueryEnum(this, pname, "getQueryParameter"))
+ const auto& slot = ValidateQuerySlotByTarget(funcName, target);
+ if (!slot)
return;
- if (!query) {
- /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1):
- * If id is not the name of a query object, or if the query object
- * named by id is currently active, then an INVALID_OPERATION error
- * is generated. pname must be QUERY_RESULT or
- * QUERY_RESULT_AVAILABLE.
- */
- ErrorInvalidOperation("getQueryObject: `query` should not be null.");
- return;
- }
+ const auto& query = *slot;
+ if (!query)
+ return ErrorInvalidOperation("%s: Query target not active.", funcName);
+
+ query->EndQuery();
- if (query->IsDeleted()) {
- // See (spec getQueryObject 1)
- ErrorInvalidOperation("getQueryObject: `query` has been deleted.");
- return;
- }
+ *slot = nullptr;
+}
- if (query->IsActive()) {
- // See (spec getQueryObject 1)
- ErrorInvalidOperation("getQueryObject: `query` is active.");
- return;
+void
+WebGLContext::GetQuery(JSContext* cx, GLenum target, GLenum pname,
+ JS::MutableHandleValue retval, const char* funcName)
+{
+ if (!funcName) {
+ funcName = "getQuery";
}
- if (!query->HasEverBeenActive()) {
- /* See (spec getQueryObject 1)
- * If this instance of WebGLQuery has never been active before, that
- * mean that query->mGLName is not a query object yet.
- */
- ErrorInvalidOperation("getQueryObject: `query` has never been active.");
+ retval.setNull();
+ if (IsContextLost())
return;
- }
- // We must wait for an event loop before the query can be available
- if (!query->mCanBeAvailable && !gfxPrefs::WebGLImmediateQueries()) {
- if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
- retval.set(JS::BooleanValue(false));
+ switch (pname) {
+ case LOCAL_GL_CURRENT_QUERY_EXT:
+ {
+ const auto& slot = ValidateQuerySlotByTarget(funcName, target);
+ if (!slot || !*slot)
+ return;
+
+ JS::Rooted<JS::Value> v(cx);
+ dom::GetOrCreateDOMReflector(cx, slot->get(), &v);
+ retval.set(v);
}
return;
- }
+
+ case LOCAL_GL_QUERY_COUNTER_BITS_EXT:
+ if (!IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query))
+ break;
- MakeContextCurrent();
- GLuint returned = 0;
- switch (pname) {
- case LOCAL_GL_QUERY_RESULT_AVAILABLE:
- gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);
- retval.set(JS::BooleanValue(returned != 0));
- return;
-
- case LOCAL_GL_QUERY_RESULT:
- gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT, &returned);
-
- if (query->mType == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
- retval.set(JS::NumberValue(returned));
+ if (target != LOCAL_GL_TIME_ELAPSED_EXT &&
+ target != LOCAL_GL_TIMESTAMP_EXT)
+ {
+ ErrorInvalidEnum("%s: Bad pname for target.", funcName);
return;
}
- /*
- * test (returned != 0) is important because ARB_occlusion_query on desktop drivers
- * return the number of samples drawed when the OpenGL ES extension
- * ARB_occlusion_query_boolean return only a boolean if a sample has been drawed.
- */
- retval.set(JS::BooleanValue(returned != 0));
+ {
+ GLint bits = 0;
+ gl->fGetQueryiv(target, pname, &bits);
+
+ if (!Has64BitTimestamps() && bits > 32) {
+ bits = 32;
+ }
+ retval.set(JS::Int32Value(bits));
+ }
return;
default:
break;
}
- ErrorInvalidEnum("getQueryObject: `pname` must be QUERY_RESULT{_AVAILABLE}.");
+ ErrorInvalidEnum("%s: Bad pname.", funcName);
+ return;
}
void
-WebGL2Context::UpdateBoundQuery(GLenum target, WebGLQuery* query)
-{
- WebGLRefPtr<WebGLQuery>& querySlot = GetQuerySlotByTarget(target);
- querySlot = query;
-}
-
-bool
-WebGL2Context::ValidateQueryTarget(GLenum target, const char* info)
+WebGLContext::GetQueryParameter(JSContext*, const WebGLQuery* query, GLenum pname,
+ JS::MutableHandleValue retval, const char* funcName)
{
- switch (target) {
- case LOCAL_GL_ANY_SAMPLES_PASSED:
- case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
- case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
- return true;
+ if (!funcName) {
+ funcName = "getQueryParameter";
+ }
- default:
- ErrorInvalidEnumInfo(info, target);
- return false;
- }
+ retval.setNull();
+ if (IsContextLost())
+ return;
+
+ if (!ValidateObject(funcName, query))
+ return;
+
+ query->GetQueryParameter(pname, retval);
}
} // namespace mozilla
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -66,17 +66,16 @@
#include "WebGLFramebuffer.h"
#include "WebGLMemoryTracker.h"
#include "WebGLObjectModel.h"
#include "WebGLProgram.h"
#include "WebGLQuery.h"
#include "WebGLSampler.h"
#include "WebGLShader.h"
#include "WebGLSync.h"
-#include "WebGLTimerQuery.h"
#include "WebGLTransformFeedback.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
#ifdef MOZ_WIDGET_COCOA
#include "nsCocoaFeatures.h"
#endif
@@ -247,37 +246,39 @@ WebGLContext::DestroyResourcesAndContext
mBoundCopyWriteBuffer = nullptr;
mBoundPixelPackBuffer = nullptr;
mBoundPixelUnpackBuffer = nullptr;
mBoundUniformBuffer = nullptr;
mCurrentProgram = nullptr;
mActiveProgramLinkInfo = nullptr;
mBoundDrawFramebuffer = nullptr;
mBoundReadFramebuffer = nullptr;
- mActiveOcclusionQuery = nullptr;
mBoundRenderbuffer = nullptr;
mBoundVertexArray = nullptr;
mDefaultVertexArray = nullptr;
mBoundTransformFeedback = nullptr;
mDefaultTransformFeedback = nullptr;
+ mQuerySlot_SamplesPassed = nullptr;
+ mQuerySlot_TFPrimsWritten = nullptr;
+ mQuerySlot_TimeElapsed = nullptr;
+
mIndexedUniformBufferBindings.clear();
//////
ClearLinkedList(mBuffers);
ClearLinkedList(mFramebuffers);
ClearLinkedList(mPrograms);
ClearLinkedList(mQueries);
ClearLinkedList(mRenderbuffers);
ClearLinkedList(mSamplers);
ClearLinkedList(mShaders);
ClearLinkedList(mSyncs);
ClearLinkedList(mTextures);
- ClearLinkedList(mTimerQueries);
ClearLinkedList(mTransformFeedbacks);
ClearLinkedList(mVertexArrays);
//////
mFakeBlack_2D_0000 = nullptr;
mFakeBlack_2D_0001 = nullptr;
mFakeBlack_CubeMap_0000 = nullptr;
@@ -1642,17 +1643,17 @@ WebGLContext::DummyReadFramebufferOperat
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
ErrorInvalidFramebufferOperation("%s: Framebuffer must be complete.",
funcName);
}
}
bool
-WebGLContext::HasTimestampBits() const
+WebGLContext::Has64BitTimestamps() const
{
// 'sync' provides glGetInteger64v either by supporting ARB_sync, GL3+, or GLES3+.
return gl->IsSupported(GLFeature::sync);
}
static bool
CheckContextLost(GLContext* gl, bool* const out_isGuilty)
{
@@ -2587,18 +2588,19 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(We
mBoundTransformFeedback,
mBoundUniformBuffer,
mCurrentProgram,
mBoundDrawFramebuffer,
mBoundReadFramebuffer,
mBoundRenderbuffer,
mBoundVertexArray,
mDefaultVertexArray,
- mActiveOcclusionQuery,
- mActiveTransformFeedbackQuery)
+ mQuerySlot_SamplesPassed,
+ mQuerySlot_TFPrimsWritten,
+ mQuerySlot_TimeElapsed)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
// If the exact way we cast to nsISupports here ever changes, fix our
// ToSupports() method.
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -98,17 +98,16 @@ class WebGLFramebuffer;
class WebGLProgram;
class WebGLQuery;
class WebGLRenderbuffer;
class WebGLSampler;
class WebGLShader;
class WebGLShaderPrecisionFormat;
class WebGLSync;
class WebGLTexture;
-class WebGLTimerQuery;
class WebGLTransformFeedback;
class WebGLUniformLocation;
class WebGLVertexArray;
namespace dom {
class Element;
class ImageData;
class OwningHTMLCanvasElementOrOffscreenCanvas;
@@ -441,17 +440,17 @@ public:
// Prepare the context for capture before compositing
void BeginComposition();
// Clean up the context after captured for compositing
void EndComposition();
// a number that increments every time we have an event that causes
// all context resources to be lost.
- uint32_t Generation() { return mGeneration.value(); }
+ uint32_t Generation() const { return mGeneration.value(); }
// This is similar to GLContext::ClearSafely, but tries to minimize the
// amount of work it does.
// It only clears the buffers we specify, and can reset its state without
// first having to query anything, as WebGL knows its state at all times.
void ForceClearFramebufferWithDefaultValues(GLbitfield bufferBits, bool fakeNoAlpha);
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
@@ -929,20 +928,34 @@ protected:
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target);
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
GLuint index);
// -----------------------------------------------------------------------------
// Queries (WebGL2ContextQueries.cpp)
protected:
- WebGLRefPtr<WebGLQuery>& GetQuerySlotByTarget(GLenum target);
+ WebGLRefPtr<WebGLQuery> mQuerySlot_SamplesPassed;
+ WebGLRefPtr<WebGLQuery> mQuerySlot_TFPrimsWritten;
+ WebGLRefPtr<WebGLQuery> mQuerySlot_TimeElapsed;
+
+ WebGLRefPtr<WebGLQuery>*
+ ValidateQuerySlotByTarget(const char* funcName, GLenum target);
- WebGLRefPtr<WebGLQuery> mActiveOcclusionQuery;
- WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery;
+public:
+ already_AddRefed<WebGLQuery> CreateQuery(const char* funcName = nullptr);
+ void DeleteQuery(WebGLQuery* query, const char* funcName = nullptr);
+ bool IsQuery(const WebGLQuery* query, const char* funcName = nullptr);
+ void BeginQuery(GLenum target, WebGLQuery* query, const char* funcName = nullptr);
+ void EndQuery(GLenum target, const char* funcName = nullptr);
+ void GetQuery(JSContext* cx, GLenum target, GLenum pname,
+ JS::MutableHandleValue retval, const char* funcName = nullptr);
+ void GetQueryParameter(JSContext* cx, const WebGLQuery* query, GLenum pname,
+ JS::MutableHandleValue retval, const char* funcName = nullptr);
+
// -----------------------------------------------------------------------------
// State and State Requests (WebGLContextState.cpp)
public:
void Disable(GLenum cap);
void Enable(GLenum cap);
bool GetStencilBits(GLint* const out_stencilBits);
bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val);
@@ -1607,45 +1620,44 @@ protected:
WebGLTexelFormat srcFormat, bool srcPremultiplied,
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize);
//////
// Returns false if `object` is null or not valid.
template<class ObjectType>
- bool ValidateObject(const char* info, ObjectType* object);
+ bool ValidateObject(const char* info, const ObjectType* object);
// Returns false if `object` is not valid. Considers null to be valid.
template<class ObjectType>
- bool ValidateObjectAllowNull(const char* info, ObjectType* object);
+ bool ValidateObjectAllowNull(const char* info, const ObjectType* object);
// Returns false if `object` is not valid, but considers deleted objects and
// null objects valid.
template<class ObjectType>
- bool ValidateObjectAllowDeletedOrNull(const char* info, ObjectType* object);
+ bool ValidateObjectAllowDeletedOrNull(const char* info, const ObjectType* object);
// Returns false if `object` is null or not valid, but considers deleted
// objects valid.
template<class ObjectType>
- bool ValidateObjectAllowDeleted(const char* info, ObjectType* object);
+ bool ValidateObjectAllowDeleted(const char* info, const ObjectType* object);
private:
// Like ValidateObject, but only for cases when `object` is known to not be
// null already.
template<class ObjectType>
- bool ValidateObjectAssumeNonNull(const char* info, ObjectType* object);
+ bool ValidateObjectAssumeNonNull(const char* info, const ObjectType* object);
private:
// -------------------------------------------------------------------------
// Context customization points
virtual WebGLVertexArray* CreateVertexArrayImpl();
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, uint32_t* alignment, const char* info) = 0;
- virtual bool ValidateQueryTarget(GLenum usage, const char* info) = 0;
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0;
public:
void ForceLoseContext(bool simulateLoss = false);
protected:
void ForceRestoreContext();
@@ -1672,17 +1684,16 @@ protected:
LinkedList<WebGLFramebuffer> mFramebuffers;
LinkedList<WebGLProgram> mPrograms;
LinkedList<WebGLQuery> mQueries;
LinkedList<WebGLRenderbuffer> mRenderbuffers;
LinkedList<WebGLSampler> mSamplers;
LinkedList<WebGLShader> mShaders;
LinkedList<WebGLSync> mSyncs;
LinkedList<WebGLTexture> mTextures;
- LinkedList<WebGLTimerQuery> mTimerQueries;
LinkedList<WebGLTransformFeedback> mTransformFeedbacks;
LinkedList<WebGLVertexArray> mVertexArrays;
WebGLRefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
// PixelStore parameters
uint32_t mPixelStore_UnpackImageHeight;
@@ -1787,17 +1798,17 @@ protected:
uint64_t mLastUseIndex;
bool mNeedsFakeNoAlpha;
bool mNeedsFakeNoDepth;
bool mNeedsFakeNoStencil;
bool mNeedsEmulatedLoneDepthStencil;
- bool HasTimestampBits() const;
+ bool Has64BitTimestamps() const;
struct ScopedMaskWorkaround {
WebGLContext& mWebGL;
const bool mFakeNoAlpha;
const bool mFakeNoDepth;
const bool mFakeNoStencil;
static bool ShouldFakeNoAlpha(WebGLContext& webgl) {
@@ -1895,17 +1906,16 @@ public:
friend class WebGLFramebuffer;
friend class WebGLRenderbuffer;
friend class WebGLProgram;
friend class WebGLQuery;
friend class WebGLBuffer;
friend class WebGLSampler;
friend class WebGLShader;
friend class WebGLSync;
- friend class WebGLTimerQuery;
friend class WebGLTransformFeedback;
friend class WebGLUniformLocation;
friend class WebGLVertexArray;
friend class WebGLVertexArrayFake;
friend class WebGLVertexArrayGL;
};
// used by DOM bindings in conjunction with GetParentObject
@@ -1917,70 +1927,70 @@ ToSupports(WebGLContext* webgl)
/**
** Template implementations
**/
template<class ObjectType>
inline bool
WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info,
- ObjectType* object)
+ const ObjectType* object)
{
if (object && !object->IsCompatibleWithContext(this)) {
ErrorInvalidOperation("%s: object from different WebGL context "
"(or older generation of this one) "
"passed as argument", info);
return false;
}
return true;
}
template<class ObjectType>
inline bool
-WebGLContext::ValidateObjectAssumeNonNull(const char* info, ObjectType* object)
+WebGLContext::ValidateObjectAssumeNonNull(const char* info, const ObjectType* object)
{
MOZ_ASSERT(object);
if (!ValidateObjectAllowDeletedOrNull(info, object))
return false;
if (object->IsDeleted()) {
ErrorInvalidValue("%s: Deleted object passed as argument.", info);
return false;
}
return true;
}
template<class ObjectType>
inline bool
-WebGLContext::ValidateObjectAllowNull(const char* info, ObjectType* object)
+WebGLContext::ValidateObjectAllowNull(const char* info, const ObjectType* object)
{
if (!object)
return true;
return ValidateObjectAssumeNonNull(info, object);
}
template<class ObjectType>
inline bool
-WebGLContext::ValidateObjectAllowDeleted(const char* info, ObjectType* object)
+WebGLContext::ValidateObjectAllowDeleted(const char* info, const ObjectType* object)
{
if (!object) {
ErrorInvalidValue("%s: null object passed as argument", info);
return false;
}
return ValidateObjectAllowDeletedOrNull(info, object);
}
template<class ObjectType>
inline bool
-WebGLContext::ValidateObject(const char* info, ObjectType* object)
+WebGLContext::ValidateObject(const char* info, const ObjectType* object)
{
if (!object) {
ErrorInvalidValue("%s: null object passed as argument", info);
return false;
}
return ValidateObjectAssumeNonNull(info, object);
}
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -259,34 +259,41 @@ WebGLContext::GetParameter(JSContext* cx
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
WebGLVertexArray* vao =
(mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
return WebGLObjectAsJSValue(cx, vao, rv);
}
}
- if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
- if (pname == LOCAL_GL_TIMESTAMP_EXT) {
- GLuint64 iv = 0;
- if (HasTimestampBits()) {
- gl->fGetInteger64v(pname, (GLint64*)&iv);
- } else {
- GenerateWarning("QUERY_COUNTER_BITS_EXT for TIMESTAMP_EXT is 0.");
+ if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
+ switch (pname) {
+ case LOCAL_GL_TIMESTAMP_EXT:
+ {
+ uint64_t val = 0;
+ if (Has64BitTimestamps()) {
+ gl->fGetInteger64v(pname, (GLint64*)&val);
+ } else {
+ gl->fGetIntegerv(pname, (GLint*)&val);
+ }
+ // TODO: JS doesn't support 64-bit integers. Be lossy and
+ // cast to double (53 bits)
+ return JS::NumberValue(val);
}
- // TODO: JS doesn't support 64-bit integers. Be lossy and
- // cast to double (53 bits)
- return JS::NumberValue(static_cast<double>(iv));
- } else if (pname == LOCAL_GL_GPU_DISJOINT_EXT) {
- // When disjoint isn't supported, leave as false.
- realGLboolean disjoint = LOCAL_GL_FALSE;
- if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
- gl->fGetBooleanv(pname, &disjoint);
+
+ case LOCAL_GL_GPU_DISJOINT_EXT:
+ {
+ MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query));
+ realGLboolean val = false;
+ gl->fGetBooleanv(pname, &val);
+ return JS::BooleanValue(val);
}
- return JS::BooleanValue(bool(disjoint));
+
+ default:
+ break;
}
}
// Privileged string params exposed by WEBGL_debug_renderer_info.
// The privilege check is done in WebGLContext::IsExtensionSupported.
// So here we just have to check that the extension is enabled.
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
switch (pname) {
--- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
+++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
@@ -7,263 +7,123 @@
#include "WebGLExtensions.h"
#include "gfxPrefs.h"
#include "GLContext.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "mozilla/dom/BindingUtils.h"
#include "WebGLContext.h"
-#include "WebGLTimerQuery.h"
+#include "WebGLQuery.h"
namespace mozilla {
WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
- , mActiveQuery(nullptr)
{
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
}
WebGLExtensionDisjointTimerQuery::~WebGLExtensionDisjointTimerQuery()
{
}
-already_AddRefed<WebGLTimerQuery>
-WebGLExtensionDisjointTimerQuery::CreateQueryEXT()
+already_AddRefed<WebGLQuery>
+WebGLExtensionDisjointTimerQuery::CreateQueryEXT() const
{
+ const char funcName[] = "createQueryEXT";
if (mIsLost)
return nullptr;
- RefPtr<WebGLTimerQuery> query = WebGLTimerQuery::Create(mContext);
- return query.forget();
+ return mContext->CreateQuery(funcName);
}
void
-WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLTimerQuery* query)
-{
- if (mIsLost)
- return;
-
- if (!mContext->ValidateObject("deleteQueryEXT", query))
- return;
-
- query->RequestDelete();
-}
-
-bool
-WebGLExtensionDisjointTimerQuery::IsQueryEXT(WebGLTimerQuery* query)
+WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLQuery* query) const
{
- if (!query)
- return false;
-
- if (!mContext->ValidateObjectAllowDeleted("isQueryEXT", query))
- return false;
-
- if (query->IsDeleted())
- return false;
-
- return true;
-}
-
-void
-WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target,
- WebGLTimerQuery* query)
-{
+ const char funcName[] = "deleteQueryEXT";
if (mIsLost)
return;
- if (!mContext->ValidateObject("beginQueryEXT", query))
- return;
-
- if (query->HasEverBeenBound() && query->Target() != target) {
- mContext->ErrorInvalidOperation("beginQueryEXT: Query is already bound"
- " to a different target.");
- return;
- }
+ mContext->DeleteQuery(query, funcName);
+}
- if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
- mContext->ErrorInvalidEnumInfo("beginQueryEXT: Can only begin on target"
- " TIME_ELAPSED_EXT.", target);
- return;
- }
+bool
+WebGLExtensionDisjointTimerQuery::IsQueryEXT(const WebGLQuery* query) const
+{
+ const char funcName[] = "isQueryEXT";
+ if (mIsLost)
+ return false;
- if (mActiveQuery) {
- mContext->ErrorInvalidOperation("beginQueryEXT: A query is already"
- " active.");
- return;
- }
-
- mContext->MakeContextCurrent();
- gl::GLContext* gl = mContext->GL();
- gl->fBeginQuery(target, query->mGLName);
- query->mTarget = LOCAL_GL_TIME_ELAPSED_EXT;
- mActiveQuery = query;
+ return mContext->IsQuery(query, funcName);
}
void
-WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target)
+WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, WebGLQuery* query) const
{
+ const char funcName[] = "beginQueryEXT";
if (mIsLost)
return;
- if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
- mContext->ErrorInvalidEnumInfo("endQueryEXT: Can only end on"
- " TIME_ELAPSED_EXT.", target);
- return;
- }
+ mContext->BeginQuery(target, query, funcName);
+}
- if (!mActiveQuery) {
- mContext->ErrorInvalidOperation("endQueryEXT: A query is not active.");
+void
+WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target) const
+{
+ const char funcName[] = "endQueryEXT";
+ if (mIsLost)
return;
- }
- mContext->MakeContextCurrent();
- mContext->GL()->fEndQuery(target);
- mActiveQuery->QueueAvailablity();
- mActiveQuery = nullptr;
+ mContext->EndQuery(target, funcName);
}
void
-WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query,
- GLenum target)
+WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery* query, GLenum target) const
{
+ const char funcName[] = "queryCounterEXT";
if (mIsLost)
return;
- if (!mContext->ValidateObject("queryCounterEXT", query))
+ if (!mContext->ValidateObject(funcName, query))
return;
- if (target != LOCAL_GL_TIMESTAMP_EXT) {
- mContext->ErrorInvalidEnumInfo("queryCounterEXT: requires"
- " TIMESTAMP_EXT.", target);
- return;
- }
-
- mContext->MakeContextCurrent();
- mContext->GL()->fQueryCounter(query->mGLName, target);
- query->mTarget = LOCAL_GL_TIMESTAMP_EXT;
- query->QueueAvailablity();
+ query->QueryCounter(funcName, target);
}
void
-WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target,
- GLenum pname,
- JS::MutableHandle<JS::Value> retval)
+WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, GLenum pname,
+ JS::MutableHandleValue retval) const
{
+ const char funcName[] = "getQueryEXT";
retval.setNull();
if (mIsLost)
return;
- mContext->MakeContextCurrent();
- switch (pname) {
- case LOCAL_GL_CURRENT_QUERY_EXT:
- if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
- mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.",
- target);
- return;
- }
- if (mActiveQuery) {
- JS::Rooted<JS::Value> v(cx);
- dom::GetOrCreateDOMReflector(cx, mActiveQuery.get(), &v);
- retval.set(v);
- } else {
- retval.set(JS::NullValue());
- }
- break;
-
- case LOCAL_GL_QUERY_COUNTER_BITS_EXT:
- if (target != LOCAL_GL_TIME_ELAPSED_EXT &&
- target != LOCAL_GL_TIMESTAMP_EXT)
- {
- mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.",
- target);
- return;
- }
-
- {
- GLint bits = 0;
- if (mContext->HasTimestampBits()) {
- mContext->GL()->fGetQueryiv(target, pname, &bits);
- }
- retval.set(JS::Int32Value(int32_t(bits)));
- }
- break;
-
- default:
- mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query property.",
- pname);
- break;
- }
+ mContext->GetQuery(cx, target, pname, retval, funcName);
}
void
WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
- WebGLTimerQuery* query,
- GLenum pname,
- JS::MutableHandle<JS::Value> retval)
+ const WebGLQuery* query, GLenum pname,
+ JS::MutableHandleValue retval) const
{
+ const char funcName[] = "getQueryObjectEXT";
retval.setNull();
if (mIsLost)
return;
- if (!mContext->ValidateObject("getQueryObjectEXT", query))
- return;
-
- if (query == mActiveQuery.get()) {
- mContext->ErrorInvalidOperation("getQueryObjectEXT: Query must not be"
- " active.");
- return;
- }
-
- mContext->MakeContextCurrent();
- // XXX: Note that the query result *may change* within the same task!
- // This does not follow the specification, which states that all calls
- // checking query results must return the same value until the event loop
- // is empty.
- switch (pname) {
- case LOCAL_GL_QUERY_RESULT_EXT:
- {
- GLuint64 result = 0;
- mContext->GL()->fGetQueryObjectui64v(query->mGLName,
- LOCAL_GL_QUERY_RESULT_EXT,
- &result);
- retval.set(JS::NumberValue(result));
- }
- break;
-
- case LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT:
- {
- GLuint avail = 0;
- mContext->GL()->fGetQueryObjectuiv(query->mGLName,
- LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT,
- &avail);
- bool canBeAvailable = query->CanBeAvailable() || gfxPrefs::WebGLImmediateQueries();
- retval.set(JS::BooleanValue(bool(avail) && canBeAvailable));
- }
- break;
-
- default:
- mContext->ErrorInvalidEnumInfo("getQueryObjectEXT: Invalid query"
- " property.", pname);
- break;
- }
+ mContext->GetQueryParameter(cx, query, pname, retval, funcName);
}
bool
WebGLExtensionDisjointTimerQuery::IsSupported(const WebGLContext* webgl)
{
webgl->MakeContextCurrent();
gl::GLContext* gl = webgl->GL();
return gl->IsSupported(gl::GLFeature::query_objects) &&
gl->IsSupported(gl::GLFeature::get_query_object_i64v) &&
gl->IsSupported(gl::GLFeature::query_counter); // provides GL_TIMESTAMP
}
-void
-WebGLExtensionDisjointTimerQuery::OnMarkLost()
-{
- mActiveQuery = nullptr;
-}
-
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery, EXT_disjoint_timer_query)
} // namespace mozilla
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -20,17 +20,16 @@ class Sequence;
namespace webgl {
class FormatUsageAuthority;
} // namespace webgl
class WebGLContext;
class WebGLShader;
class WebGLQuery;
-class WebGLTimerQuery;
class WebGLVertexArray;
class WebGLExtensionBase
: public nsWrapperCache
, public WebGLContextBoundObject
{
public:
explicit WebGLExtensionBase(WebGLContext* webgl);
@@ -365,36 +364,27 @@ public:
class WebGLExtensionDisjointTimerQuery
: public WebGLExtensionBase
{
public:
explicit WebGLExtensionDisjointTimerQuery(WebGLContext* webgl);
virtual ~WebGLExtensionDisjointTimerQuery();
- already_AddRefed<WebGLTimerQuery> CreateQueryEXT();
- void DeleteQueryEXT(WebGLTimerQuery* query);
- bool IsQueryEXT(WebGLTimerQuery* query);
- void BeginQueryEXT(GLenum target, WebGLTimerQuery* query);
- void EndQueryEXT(GLenum target);
- void QueryCounterEXT(WebGLTimerQuery* query, GLenum target);
- void GetQueryEXT(JSContext *cx, GLenum target, GLenum pname,
- JS::MutableHandle<JS::Value> retval);
- void GetQueryObjectEXT(JSContext *cx, WebGLTimerQuery* query,
- GLenum pname,
- JS::MutableHandle<JS::Value> retval);
+ already_AddRefed<WebGLQuery> CreateQueryEXT() const;
+ void DeleteQueryEXT(WebGLQuery* query) const;
+ bool IsQueryEXT(const WebGLQuery* query) const;
+ void BeginQueryEXT(GLenum target, WebGLQuery* query) const;
+ void EndQueryEXT(GLenum target) const;
+ void QueryCounterEXT(WebGLQuery* query, GLenum target) const;
+ void GetQueryEXT(JSContext* cx, GLenum target, GLenum pname,
+ JS::MutableHandleValue retval) const;
+ void GetQueryObjectEXT(JSContext* cx, const WebGLQuery* query,
+ GLenum pname, JS::MutableHandleValue retval) const;
static bool IsSupported(const WebGLContext*);
DECL_WEBGL_EXTENSION_GOOP
-
-private:
- virtual void OnMarkLost() override;
-
- /**
- * An active TIME_ELAPSED query participating in a begin/end block.
- */
- WebGLRefPtr<WebGLTimerQuery> mActiveQuery;
};
} // namespace mozilla
#endif // WEBGL_EXTENSIONS_H_
--- a/dom/canvas/WebGLObjectModel.cpp
+++ b/dom/canvas/WebGLObjectModel.cpp
@@ -11,15 +11,15 @@ namespace mozilla {
WebGLContextBoundObject::WebGLContextBoundObject(WebGLContext* webgl)
: mContext(webgl)
, mContextGeneration(webgl->Generation())
{
}
bool
-WebGLContextBoundObject::IsCompatibleWithContext(WebGLContext* other)
+WebGLContextBoundObject::IsCompatibleWithContext(const WebGLContext* other) const
{
return (mContext == other &&
mContextGeneration == other->Generation());
}
} // namespace mozilla
--- a/dom/canvas/WebGLObjectModel.h
+++ b/dom/canvas/WebGLObjectModel.h
@@ -262,17 +262,17 @@ protected:
// This class is a mixin for objects that are tied to a specific
// context (which is to say, all of them). They provide initialization
// as well as comparison with the current context.
class WebGLContextBoundObject
{
public:
explicit WebGLContextBoundObject(WebGLContext* webgl);
- bool IsCompatibleWithContext(WebGLContext* other);
+ bool IsCompatibleWithContext(const WebGLContext* other) const;
WebGLContext* const mContext;
protected:
const uint32_t mContextGeneration;
};
// this class is a mixin for GL objects that have dimensions
// that we need to track.
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -7,51 +7,267 @@
#include "GLContext.h"
#include "mozilla/dom/WebGL2RenderingContextBinding.h"
#include "nsContentUtils.h"
#include "WebGLContext.h"
namespace mozilla {
-JSObject*
-WebGLQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
+class AvailableRunnable final : public Runnable
{
- return dom::WebGLQueryBinding::Wrap(cx, this, givenProto);
+ const RefPtr<WebGLQuery> mQuery;
+
+public:
+ explicit AvailableRunnable(WebGLQuery* query)
+ : mQuery(query)
+ { }
+
+ NS_IMETHOD Run() override {
+ mQuery->mCanBeAvailable = true;
+ return NS_OK;
+ }
+};
+
+////
+
+static GLuint
+GenQuery(gl::GLContext* gl)
+{
+ gl->MakeCurrent();
+
+ GLuint ret = 0;
+ gl->fGenQueries(1, &ret);
+ return ret;
}
WebGLQuery::WebGLQuery(WebGLContext* webgl)
: WebGLContextBoundObject(webgl)
+ , mGLName(GenQuery(mContext->gl))
+ , mTarget(0)
+ , mIsActive(false)
, mCanBeAvailable(false)
- , mGLName(0)
- , mType(0)
{
mContext->mQueries.insertBack(this);
-
- mContext->MakeContextCurrent();
- mContext->gl->fGenQueries(1, &mGLName);
}
void
WebGLQuery::Delete()
{
mContext->MakeContextCurrent();
mContext->gl->fDeleteQueries(1, &mGLName);
LinkedListElement<WebGLQuery>::removeFrom(mContext->mQueries);
}
+////
+
+static GLenum
+TargetForDriver(const gl::GLContext* gl, GLenum target)
+{
+ switch (target) {
+ case LOCAL_GL_ANY_SAMPLES_PASSED:
+ case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ break;
+
+ default:
+ return target;
+ }
+
+ if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean))
+ return target;
+
+ if (gl->IsSupported(gl::GLFeature::occlusion_query2))
+ return LOCAL_GL_ANY_SAMPLES_PASSED;
+
+ return LOCAL_GL_SAMPLES_PASSED;
+}
+
bool
-WebGLQuery::IsActive() const
+WebGLQuery::BeginQuery(GLenum target)
+{
+ const char funcName[] = "beginQuery";
+
+ if (mTarget && target != mTarget) {
+ mContext->ErrorInvalidOperation("%s: Queries cannot change targets.", funcName);
+ return false;
+ }
+
+ ////
+
+ mTarget = target;
+ mIsActive = true;
+
+ ////
+
+ const auto& gl = mContext->gl;
+ gl->MakeCurrent();
+
+ const auto driverTarget = TargetForDriver(gl, mTarget);
+ gl->fBeginQuery(driverTarget, mGLName);
+
+ return true;
+}
+
+void
+WebGLQuery::EndQuery()
+{
+ mIsActive = false;
+ mCanBeAvailable = false;
+
+ ////
+
+ const auto& gl = mContext->gl;
+ gl->MakeCurrent();
+
+ const auto driverTarget = TargetForDriver(gl, mTarget);
+ gl->fEndQuery(driverTarget);
+
+ ////
+
+ NS_DispatchToCurrentThread(new AvailableRunnable(this));
+}
+
+void
+WebGLQuery::GetQueryParameter(GLenum pname, JS::MutableHandleValue retval) const
{
- if (!HasEverBeenActive())
+ const char funcName[] = "getQueryParameter";
+
+ switch (pname) {
+ case LOCAL_GL_QUERY_RESULT_AVAILABLE:
+ case LOCAL_GL_QUERY_RESULT:
+ break;
+
+ default:
+ mContext->ErrorInvalidEnum("%s: Invalid pname: %s", funcName,
+ mContext->EnumName(pname));
+ return;
+ }
+
+ if (!mTarget) {
+ mContext->ErrorInvalidOperation("%s: Query has never been active.", funcName);
+ return;
+ }
+
+ if (mIsActive)
+ return mContext->ErrorInvalidOperation("%s: Query is still active.", funcName);
+
+ // End of validation
+ ////
+
+ // We must usually wait for an event loop before the query can be available.
+ const bool canBeAvailable = (mCanBeAvailable || gfxPrefs::WebGLImmediateQueries());
+ if (!canBeAvailable) {
+ if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
+ retval.set(JS::BooleanValue(false));
+ }
+ return;
+ }
+
+ const auto& gl = mContext->gl;
+ gl->MakeCurrent();
+
+ uint64_t val = 0;
+ switch (pname) {
+ case LOCAL_GL_QUERY_RESULT_AVAILABLE:
+ gl->fGetQueryObjectuiv(mGLName, pname, (GLuint*)&val);
+ retval.set(JS::BooleanValue(bool(val)));
+ return;
+
+ case LOCAL_GL_QUERY_RESULT:
+ switch (mTarget) {
+ case LOCAL_GL_TIME_ELAPSED_EXT:
+ case LOCAL_GL_TIMESTAMP_EXT:
+ if (mContext->Has64BitTimestamps()) {
+ gl->fGetQueryObjectui64v(mGLName, pname, &val);
+ break;
+ }
+ MOZ_FALLTHROUGH;
+
+ default:
+ gl->fGetQueryObjectuiv(mGLName, LOCAL_GL_QUERY_RESULT, (GLuint*)&val);
+ break;
+ }
+
+ switch (mTarget) {
+ case LOCAL_GL_ANY_SAMPLES_PASSED:
+ case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ retval.set(JS::BooleanValue(bool(val)));
+ break;
+
+ case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ case LOCAL_GL_TIME_ELAPSED_EXT:
+ case LOCAL_GL_TIMESTAMP_EXT:
+ retval.set(JS::NumberValue(val));
+ break;
+
+ default:
+ MOZ_CRASH("Bad `mTarget`.");
+ }
+ return;
+
+ default:
+ MOZ_CRASH("Bad `pname`.");
+ }
+}
+
+bool
+WebGLQuery::IsQuery() const
+{
+ if (IsDeleted())
return false;
- WebGLRefPtr<WebGLQuery>& targetSlot = mContext->GetQuerySlotByTarget(mType);
+ if (!mTarget)
+ return false;
+
+ return true;
+}
+
+void
+WebGLQuery::DeleteQuery()
+{
+ if (IsDeleted())
+ return;
+
+ if (mIsActive) {
+ EndQuery();
+ }
+
+ RequestDelete();
+}
- return targetSlot.get() == this;
+void
+WebGLQuery::QueryCounter(const char* funcName, GLenum target)
+{
+ if (target != LOCAL_GL_TIMESTAMP_EXT) {
+ mContext->ErrorInvalidEnum("%s: `target` must be TIMESTAMP_EXT.", funcName,
+ target);
+ return;
+ }
+
+ if (mTarget && target != mTarget) {
+ mContext->ErrorInvalidOperation("%s: Queries cannot change targets.", funcName);
+ return;
+ }
+
+ mTarget = target;
+ mCanBeAvailable = false;
+
+ const auto& gl = mContext->gl;
+ gl->MakeCurrent();
+ gl->fQueryCounter(mGLName, mTarget);
+
+ NS_DispatchToCurrentThread(new AvailableRunnable(this));
+}
+
+////
+
+JSObject*
+WebGLQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
+{
+ return dom::WebGLQueryBinding::Wrap(cx, this, givenProto);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLQuery)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLQuery, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLQuery, Release)
} // namespace mozilla
--- a/dom/canvas/WebGLQuery.h
+++ b/dom/canvas/WebGLQuery.h
@@ -15,61 +15,55 @@
namespace mozilla {
class WebGLQuery final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLQuery>
, public LinkedListElement<WebGLQuery>
, public WebGLContextBoundObject
{
-public:
- explicit WebGLQuery(WebGLContext* webgl);
-
- class AvailableRunnable final : public Runnable
- {
- public:
- explicit AvailableRunnable(WebGLQuery* query) : mQuery(query) { }
-
- NS_IMETHOD Run() override {
- mQuery->mCanBeAvailable = true;
- return NS_OK;
- }
- private:
- const RefPtr<WebGLQuery> mQuery;
- };
+ friend class AvailableRunnable;
+ friend class WebGLRefCountedObject<WebGLQuery>;
- bool IsActive() const;
-
- bool HasEverBeenActive() const {
- return mType != 0;
- }
+public:
+ const GLuint mGLName;
+private:
+ GLenum mTarget;
+ bool mIsActive;
- // WebGLRefCountedObject
- void Delete();
+ bool mCanBeAvailable; // Track whether the event loop has spun
- // nsWrapperCache
- WebGLContext* GetParentObject() const {
- return mContext;
- }
+ ////
+public:
+ bool IsActive() const { return mIsActive; }
- // NS
- virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
+ ////
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQuery)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQuery)
- // Track whether the event loop has spun
- bool mCanBeAvailable;
+ explicit WebGLQuery(WebGLContext* webgl);
private:
~WebGLQuery() {
DeleteOnce();
};
- GLuint mGLName;
- GLenum mType;
+ // WebGLRefCountedObject
+ void Delete();
+
+public:
+ WebGLContext* GetParentObject() const { return mContext; }
+ virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
- friend class WebGL2Context;
+ ////
+
+ bool BeginQuery(GLenum target);
+ void DeleteQuery();
+ void EndQuery();
+ void GetQueryParameter(GLenum pname, JS::MutableHandleValue retval) const;
+ bool IsQuery() const;
+ void QueryCounter(const char* funcName, GLenum target);
};
} // namespace mozilla
#endif // WEBGL_QUERY_H_
deleted file mode 100644
--- a/dom/canvas/WebGLTimerQuery.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WebGLTimerQuery.h"
-
-#include "GLContext.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "nsContentUtils.h"
-#include "WebGLContext.h"
-#include "nsThreadUtils.h"
-
-namespace mozilla {
-
-JSObject*
-WebGLTimerQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
-{
- return dom::WebGLTimerQueryEXTBinding::Wrap(cx, this, givenProto);
-}
-
-WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint name)
- : WebGLContextBoundObject(webgl)
- , mGLName(name)
- , mTarget(LOCAL_GL_NONE)
- , mCanBeAvailable(false)
-{
- mContext->mTimerQueries.insertBack(this);
-}
-
-WebGLTimerQuery::~WebGLTimerQuery()
-{
- DeleteOnce();
-}
-
-WebGLTimerQuery*
-WebGLTimerQuery::Create(WebGLContext* webgl)
-{
- GLuint name = 0;
- webgl->MakeContextCurrent();
- webgl->gl->fGenQueries(1, &name);
- return new WebGLTimerQuery(webgl, name);
-}
-
-void
-WebGLTimerQuery::Delete()
-{
- gl::GLContext* gl = mContext->GL();
-
- gl->MakeCurrent();
- gl->fDeleteQueries(1, &mGLName);
-
- LinkedListElement<WebGLTimerQuery>::removeFrom(mContext->mTimerQueries);
-}
-
-WebGLContext*
-WebGLTimerQuery::GetParentObject() const
-{
- return mContext;
-}
-
-void
-WebGLTimerQuery::QueueAvailablity()
-{
- RefPtr<WebGLTimerQuery> self = this;
- NS_DispatchToCurrentThread(NS_NewRunnableFunction([self] { self->mCanBeAvailable = true; }));
-}
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTimerQuery)
-
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTimerQuery, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTimerQuery, Release)
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/canvas/WebGLTimerQuery.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WEBGL_TIMER_QUERY_H_
-#define WEBGL_TIMER_QUERY_H_
-
-#include "GLConsts.h"
-#include "nsWrapperCache.h"
-#include "WebGLObjectModel.h"
-
-namespace mozilla {
-
-class WebGLTimerQuery final
- : public nsWrapperCache
- , public WebGLRefCountedObject<WebGLTimerQuery>
- , public LinkedListElement<WebGLTimerQuery>
- , public WebGLContextBoundObject
-{
-public:
- static WebGLTimerQuery* Create(WebGLContext* webgl);
-
- void Delete();
-
- bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
- bool CanBeAvailable() const { return mCanBeAvailable; }
- void QueueAvailablity();
- GLenum Target() const { return mTarget; }
-
- WebGLContext* GetParentObject() const;
-
- // NS
- virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
-
- const GLenum mGLName;
-
- NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTimerQuery)
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTimerQuery)
-
-private:
- WebGLTimerQuery(WebGLContext* webgl, GLuint name);
- ~WebGLTimerQuery();
-
- GLenum mTarget;
- bool mCanBeAvailable;
-
- friend class WebGLExtensionDisjointTimerQuery;
-};
-
-} // namespace mozilla
-
-#endif // WEBGL_TIMER_QUERY_H_
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -144,17 +144,16 @@ UNIFIED_SOURCES += [
'WebGLSampler.cpp',
'WebGLShader.cpp',
'WebGLShaderPrecisionFormat.cpp',
'WebGLShaderValidator.cpp',
'WebGLSync.cpp',
'WebGLTexelConversions.cpp',
'WebGLTexture.cpp',
'WebGLTextureUpload.cpp',
- 'WebGLTimerQuery.cpp',
'WebGLTransformFeedback.cpp',
'WebGLUniformLocation.cpp',
'WebGLValidateStrings.cpp',
'WebGLVertexArray.cpp',
'WebGLVertexArrayFake.cpp',
'WebGLVertexArrayGL.cpp',
'WebGLVertexArrayObject.cpp',
'WebGLVertexAttribData.cpp',