From f26e4d546b1cd0dc469eca31701b2e3352f3ad94 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Wed, 8 Jan 2020 22:19:26 +0000 Subject: [PATCH] Bug 1477756 - Fix non-webgl CI tests. r=handyman * Revert some partial webgl+oop+vr code. * More missing FuncScope. * Fix compile errors. * Refactor some ifdef'd code to branch and compile on all platforms. * -Wno-error=unused-result for GCC to allow for (void)MustUse(). Depends on D55739 Differential Revision: https://phabricator.services.mozilla.com/D56169 --HG-- extra : moz-landing-system : lando --- dom/canvas/ClientWebGLContext.cpp | 38 ++-- dom/canvas/ClientWebGLContext.h | 36 +++- dom/canvas/HostWebGLContext.cpp | 5 + dom/canvas/HostWebGLContext.h | 21 +- dom/canvas/ProducerConsumerQueue.h | 5 +- dom/canvas/WebGLCommandQueue.h | 197 +++--------------- dom/canvas/WebGLContext.cpp | 118 +++++------ dom/canvas/WebGLContext.h | 22 +- dom/canvas/WebGLMethodDispatcher.h | 1 + dom/canvas/WebGLParent.cpp | 2 +- dom/canvas/WebGLParent.h | 2 +- dom/canvas/WebGLTypes.h | 8 +- dom/canvas/moz.build | 3 + .../test/webgl-conf/generated-mochitest.ini | 2 +- .../test/webgl-conf/mochitest-errata.ini | 2 +- dom/html/HTMLCanvasElement.cpp | 6 +- gfx/gl/GLBlitHelper.cpp | 1 + gfx/vr/ipc/PVRLayer.ipdl | 5 +- gfx/vr/ipc/VRLayerChild.cpp | 66 +++++- gfx/vr/ipc/VRLayerChild.h | 3 + gfx/vr/ipc/VRLayerParent.cpp | 64 +----- gfx/vr/ipc/VRLayerParent.h | 18 +- gfx/vr/moz.build | 8 +- 23 files changed, 256 insertions(+), 377 deletions(-) diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp index 34430f2f357a..deeecc12e884 100644 --- a/dom/canvas/ClientWebGLContext.cpp +++ b/dom/canvas/ClientWebGLContext.cpp @@ -359,18 +359,13 @@ inline void DefaultOrVoid() { return; } -// If we are running WebGL in this process then call the HostWebGLContext -// method directly. Otherwise, dispatch over IPC. -template < - typename MethodType, MethodType method, - typename ReturnType = typename FunctionTypeTraits::ReturnType, - size_t Id = WebGLMethodDispatcher::Id(), - typename... Args> -ReturnType ClientWebGLContext::Run(Args&&... aArgs) const { +template +ReturnType RunOn(const ClientWebGLContext& context, Args&&... aArgs) { const auto notLost = - mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. - if (!mNotLost) return DefaultOrVoid(); - const auto& inProcessContext = mNotLost->inProcess; + context.mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. + if (!notLost) return DefaultOrVoid(); + const auto& inProcessContext = notLost->inProcess; if (inProcessContext) { return ((inProcessContext.get())->*method)(std::forward(aArgs)...); } @@ -379,6 +374,20 @@ ReturnType ClientWebGLContext::Run(Args&&... aArgs) const { // aArgs...); } +// If we are running WebGL in this process then call the HostWebGLContext +// method directly. Otherwise, dispatch over IPC. +template +// template < +// typename MethodType, MethodType method, +// typename ReturnType, size_t Id, +// typename... Args> +ReturnType ClientWebGLContext::Run(Args&&... aArgs) const { + return RunOn(), Args...>( + *this, std::forward(aArgs)...); +} + // ------------------------------------------------------------------------- // Client-side helper methods. Dispatch to a Host method. // ------------------------------------------------------------------------- @@ -446,7 +455,12 @@ void ClientWebGLContext::EndComposition() { void ClientWebGLContext::Present() { Run(); } -void ClientWebGLContext::ClearVRFrame() { Run(); } +void ClientWebGLContext::ClearVRFrame() const { Run(); } + +RefPtr ClientWebGLContext::GetVRFrame() + const { + return Run(); +} already_AddRefed ClientWebGLContext::GetCanvasLayer( nsDisplayListBuilder* builder, Layer* oldLayer, LayerManager* manager) { diff --git a/dom/canvas/ClientWebGLContext.h b/dom/canvas/ClientWebGLContext.h index 07f13e350472..87de5d4fe29b 100644 --- a/dom/canvas/ClientWebGLContext.h +++ b/dom/canvas/ClientWebGLContext.h @@ -171,12 +171,12 @@ class ContextGenerationInfo final { std::vector mGenericVertexAttribs; - std::array mColorWriteMask = {true, true, true, true}; + std::array mColorWriteMask = {{true, true, true, true}}; std::array mScissor = {}; std::array mViewport = {}; - std::array mClearColor = {0, 0, 0, 0}; - std::array mBlendColor = {0, 0, 0, 0}; - std::array mDepthRange = {0, 1}; + std::array mClearColor = {{0, 0, 0, 0}}; + std::array mBlendColor = {{0, 0, 0, 0}}; + std::array mDepthRange = {{0, 1}}; std::vector mCompressedTextureFormats; @@ -826,10 +826,14 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal, nsCString text; text.AppendPrintf("WebGL warning: %s: ", FuncName()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat-security" +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wformat-security" +#endif text.AppendPrintf(format, args...); -#pragma clang diagnostic pop +#ifdef __clang__ +# pragma clang diagnostic pop +#endif EnqueueErrorImpl(error, text); } @@ -979,7 +983,8 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal, void Present(); - void ClearVRFrame(); + RefPtr GetVRFrame() const; + void ClearVRFrame() const; private: const uvec2& DrawingBufferSize(); @@ -2114,10 +2119,21 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal, template friend struct WebGLClientDispatcher; - // If we are running WebGL in this process then call the HostWebGLContext - // method directly. Otherwise, dispatch over IPC. template + friend ReturnType RunOn(const ClientWebGLContext& context, Args&&... aArgs); + + // If we are running WebGL in this process then call the HostWebGLContext + // method directly. Otherwise, dispatch over IPC. + // template ::ReturnType, size_t Id = + // WebGLMethodDispatcher::Id(), typename... Args> + // ReturnType Run(Args&&... aArgs) const; + template < + typename MethodType, MethodType method, + typename ReturnType = typename FunctionTypeTraits::ReturnType, + typename... Args> ReturnType Run(Args&&... aArgs) const; // ------------------------------------------------------------------------- diff --git a/dom/canvas/HostWebGLContext.cpp b/dom/canvas/HostWebGLContext.cpp index 3bbd950c3cd5..f94f5b29c5e0 100644 --- a/dom/canvas/HostWebGLContext.cpp +++ b/dom/canvas/HostWebGLContext.cpp @@ -100,6 +100,11 @@ void HostWebGLContext::JsWarning(const std::string& text) const { (void)mOwnerData.outOfProcess->mParent.SendJsWarning(text); } +RefPtr HostWebGLContext::GetVRFrame() + const { + return mContext->GetVRFrame(); +} + ////////////////////////////////////////////// // Creation diff --git a/dom/canvas/HostWebGLContext.h b/dom/canvas/HostWebGLContext.h index 2663f6585212..d2ada15b03f6 100644 --- a/dom/canvas/HostWebGLContext.h +++ b/dom/canvas/HostWebGLContext.h @@ -130,12 +130,8 @@ class HostWebGLContext final : public SupportsWeakPtr { AutoResolveT(const HostWebGLContext& parent, const ObjectId id) : mParent(parent), mId(id) {} - template - T* As() const = delete; - #define _(X) \ - template <> \ - WebGL##X* As() const { \ + WebGL##X* As(WebGL##X*) const { \ const auto maybe = MaybeFind(mParent.m##X##Map, mId); \ if (!maybe) return nullptr; \ return maybe->get(); \ @@ -156,19 +152,22 @@ class HostWebGLContext final : public SupportsWeakPtr { #undef _ template MOZ_IMPLICIT operator T*() const { - return As(); + T* coercer = nullptr; + return As(coercer); } template MOZ_IMPLICIT operator const T*() const { - return As(); + T* coercer = nullptr; + return As(coercer); } }; AutoResolveT AutoResolve(const ObjectId id) const { return {*this, id}; } template T* ById(const ObjectId id) const { - return AutoResolve(id).As(); + T* coercer = nullptr; + return AutoResolve(id).As(coercer); } // ------------------------------------------------------------------------- @@ -183,7 +182,7 @@ class HostWebGLContext final : public SupportsWeakPtr { } void Present() { mContext->Present(); } - void ClearVRFrame() { mContext->ClearVRFrame(); } + void ClearVRFrame() const { mContext->ClearVRFrame(); } Maybe InitializeCanvasRenderer(layers::LayersBackend backend) { return mContext->InitializeCanvasRenderer(backend); @@ -782,9 +781,7 @@ class HostWebGLContext final : public SupportsWeakPtr { // Etc public: - already_AddRefed GetVRFrame() const { - return mContext->GetVRFrame(); - } + RefPtr GetVRFrame() const; protected: WebGL2Context* GetWebGL2Context() const { diff --git a/dom/canvas/ProducerConsumerQueue.h b/dom/canvas/ProducerConsumerQueue.h index e845a35915e3..53a7df672422 100644 --- a/dom/canvas/ProducerConsumerQueue.h +++ b/dom/canvas/ProducerConsumerQueue.h @@ -1160,10 +1160,7 @@ class Consumer : public detail::PcqBase { : status; } - template <> - PcqStatus TryPeekRemoveHelper<>(ConsumerView&) { - return PcqStatus::Success; - } + PcqStatus TryPeekRemoveHelper(ConsumerView&) { return PcqStatus::Success; } // If an item is available then it is copied into aArg. The item is skipped // over if aArg is null. diff --git a/dom/canvas/WebGLCommandQueue.h b/dom/canvas/WebGLCommandQueue.h index 8e3af1eb9eb0..9ede489ceb4f 100644 --- a/dom/canvas/WebGLCommandQueue.h +++ b/dom/canvas/WebGLCommandQueue.h @@ -6,8 +6,10 @@ #ifndef WEBGLCOMMANDQUEUE_H_ #define WEBGLCOMMANDQUEUE_H_ +#include "mozilla/FunctionTypeTraits.h" #include "mozilla/dom/ProducerConsumerQueue.h" #include "mozilla/ipc/IPDLParamTraits.h" +#include // Get around a bug in Clang related to __thiscall method pointers #if defined(_M_IX86) @@ -24,8 +26,6 @@ using mozilla::webgl::PcqStatus; using mozilla::webgl::Producer; using mozilla::webgl::ProducerConsumerQueue; -template -struct FunctionDispatcher; template struct MethodDispatcher; @@ -84,8 +84,7 @@ class CommandSource : public BasicSource { aCommand, aArgs...); } - template <> - PcqStatus InsertCommand<>(Command aCommand) { + PcqStatus InsertCommand(Command aCommand) { return this->mProducer->TryWaitInsert(Nothing() /* wait forever */, aCommand); } @@ -202,17 +201,6 @@ class CommandSink : public BasicSink { return true; } - template - bool DispatchAsyncFunction(ReturnType (*aFunc)(Args...)) { - std::tuple::Type>::Type...> - args; - if (!ReadArgs(args)) { - return false; - } - CallFunction(aFunc, args, std::index_sequence_for{}); - return true; - } - // void return value, non-const method variant template bool DispatchAsyncMethod(T* aObj, void (T::*aMethod)(Args...)) { @@ -239,19 +227,6 @@ class CommandSink : public BasicSink { return true; } - // void return value form of above - template - bool DispatchAsyncFunction(void (*aFunc)(Args...)) { - std::tuple::Type>::Type...> - args; - if (!ReadArgs(args)) { - return false; - } - - CallVoidFunction(aFunc, args, std::index_sequence_for{}); - return true; - } - protected: /** * Implementations will usually be something like a big switch statement @@ -276,29 +251,19 @@ class CommandSink : public BasicSink { return status; } - template <> PcqStatus CallTryRemove(std::tuple<>& aArgs, std::make_integer_sequence) { return PcqStatus::Success; } template ::ReturnType> - ReturnType CallMethod(T& aObj, MethodType aMethod, std::tuple& aArgs, - std::index_sequence) { + size_t... Indices, typename ReturnType> + std::result_of CallMethod(T& aObj, MethodType aMethod, + std::tuple& aArgs, + std::index_sequence) { return (aObj.*aMethod)(std::forward(std::get(aArgs))...); } - template ::ReturnType> - ReturnType CallFunction(FunctionType aFunc, std::tuple& aArgs, - std::index_sequence) { - return (*aFunc)(std::forward(std::get(aArgs))...); - } - template void CallVoidMethod(T& aObj, MethodType aMethod, std::tuple& aArgs, @@ -306,12 +271,6 @@ class CommandSink : public BasicSink { (aObj.*aMethod)(std::forward(std::get(aArgs))...); } - template - void CallVoidFunction(FunctionType aFunc, std::tuple& aArgs, - std::index_sequence) { - (*aFunc)(std::forward(std::get(aArgs))...); - } - template bool ReadArgs(std::tuple& aArgs) { PcqStatus status = CallTryRemove(aArgs, std::index_sequence_for{}); @@ -477,21 +436,6 @@ class SyncCommandSink : public CommandSink { } #endif - template - bool DispatchSyncFunction(ReturnType (*aFunc)(Args...)) { - std::tuple::Type>::Type...> - args; - if (!BaseType::ReadArgs(args)) { - WriteNAK(); - return false; - } - - ReturnType response = - BaseType::CallFunction(aFunc, args, std::index_sequence_for{}); - - return WriteACK(response); - } - // __cdecl/__thiscall non-const void method variant template bool DispatchSyncMethod(T& aObj, void SINK_FCN_CC (T::*aMethod)(Args...)) { @@ -556,19 +500,6 @@ class SyncCommandSink : public CommandSink { } #endif - template - bool DispatchSyncFunction(void (*aFunc)(Args...)) { - std::tuple::Type>::Type...> - args; - if (!BaseType::ReadArgs(args)) { - WriteNAK(); - return false; - } - - BaseType::CallVoidFunction(aFunc, args, std::index_sequence_for{}); - return WriteACK(); - } - protected: template bool WriteArgs(const Args&... aArgs) { @@ -607,36 +538,6 @@ struct CommandDispatchDriver { } }; -/** - * This CommandDispatcher provides helper methods that subclasses can - * use to dispatch sync/async commands to a function via a CommandSink. - * See DECLARE_FUNCTION_DISPATCHER and DEFINE_FUNCTION_DISPATCHER. - */ -template -struct FunctionDispatcher { - using SinkType = _SinkType; - template - struct DispatchFunction; - - // Specialization for dispatching asynchronous functions - template <> - struct DispatchFunction { - template - static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, FunctionType function) { - return aSink.DispatchAsyncFunction(function); - } - }; - - // Specialization for dispatching synchronous functions - template <> - struct DispatchFunction { - template - static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, FunctionType function) { - return aSink.DispatchSyncFunction(function); - } - }; -}; - /** * This CommandDispatcher provides helper methods that subclasses can * use to dispatch sync/async commands to a method via a CommandSink. @@ -647,46 +548,29 @@ struct MethodDispatcher { using SinkType = _SinkType; template struct DispatchMethod; + /* + // Specialization for dispatching asynchronous methods + template + struct DispatchMethod { + template + static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType mMethod, + ObjectType& aObj) { + return aSink.DispatchMethod(aObj, mMethod); + } + }; - // Specialization for dispatching asynchronous methods - template <> - struct DispatchMethod { - template - static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType mMethod, - ObjectType& aObj) { - return aSink.DispatchAsyncMethod(aObj, mMethod); - } - }; - - // Specialization for dispatching synchronous methods - template <> - struct DispatchMethod { - template - static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType aMethod, - ObjectType& aObj) { - return aSink.DispatchSyncMethod(aObj, aMethod); - } - }; + // Specialization for dispatching synchronous methods + template <> + struct DispatchMethod { + template + static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType aMethod, + ObjectType& aObj) { + return aSink.DispatchSyncMethod(aObj, aMethod); + } + }; + */ }; -// Declares a FunctionDispatcher with the given name and CommandSink type. -#define DECLARE_FUNCTION_DISPATCHER(_DISPATCHER, _SINKTYPE) \ - struct _DISPATCHER : public FunctionDispatcher<_DISPATCHER, _SINKTYPE> { \ - template \ - static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId) { \ - MOZ_ASSERT_UNREACHABLE("Unhandled command ID"); \ - return false; \ - } \ - template \ - static MOZ_ALWAYS_INLINE bool Dispatch(SinkType& aSink); \ - template \ - struct FuncInfo; \ - template \ - static constexpr CommandSyncType SyncType(); \ - template \ - static constexpr size_t Id(); \ - }; - // Declares a MethodDispatcher with the given name and CommandSink type. // The ObjectType is the type of the object this class will dispatch methods to. #define DECLARE_METHOD_DISPATCHER(_DISPATCHER, _SINKTYPE, _OBJECTTYPE) \ @@ -708,33 +592,6 @@ struct MethodDispatcher { static constexpr size_t Id(); \ }; -// Defines a handler in the given dispatcher for the command with the given -// id. The handler uses a CommandSink to read parameters, call the -// given function using the given synchronization protocol, and provide -// compile-time lookup of the ID by function. -#define DEFINE_FUNCTION_DISPATCHER(_DISPATCHER, _ID, _FUNC, _SYNC) \ - template <> \ - bool _DISPATCHER::DispatchCommand<_ID>(size_t aId, SinkType & aSink) { \ - return CommandDispatchDriver<_DISPATCHER>::DispatchCommandHelper(aId, \ - aSink); \ - } \ - template <> \ - bool _DISPATCHER::Dispatch<_ID>(SinkType & aSink) { \ - return DispatchFunction<_SYNC>::Run(aSink, &_FUNC); \ - } \ - template <> \ - struct _DISPATCHER::FuncInfo<_ID> { \ - using FuncType = decltype(&_FUNC); \ - }; \ - template <> \ - constexpr CommandSyncType _DISPATCHER::SyncType<_ID>() { \ - return _SYNC; \ - } \ - template <> \ - constexpr size_t _DISPATCHER::Id() { \ - return _ID; \ - } - // Defines a handler in the given dispatcher for the command with the given // id. The handler uses a CommandSink to read parameters, call the // given method using the given synchronization protocol, and provide diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 6f1ec0ab04f8..74d2f39dd3a4 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -158,6 +158,7 @@ WebGLContext::WebGLContext(HostWebGLContext& host, mMsaaSamples((uint8_t)StaticPrefs::webgl_msaa_samples()), mRequestedSize(desc.size) { host.mContext = this; + const FuncScope funcScope(*this, ""); if (mOptions.antialias && !StaticPrefs::webgl_msaa_force()) { const nsCOMPtr gfxInfo = services::GetGfxInfo(); @@ -311,6 +312,8 @@ static bool HasAcceleratedLayers(const nsCOMPtr& gfxInfo) { bool WebGLContext::CreateAndInitGL( bool forceEnabled, std::vector* const out_failReasons) { + const FuncScope funcScope(*this, ""); + // Can't use WebGL in headless mode. if (gfxPlatform::IsHeadless()) { FailureReason reason; @@ -545,7 +548,7 @@ bool WebGLContext::CreateAndInitGL( bool WebGLContext::EnsureDefaultFB() { if (mDefaultFB) { - MOZ_ASSERT(*uvec2::From(mDefaultFB->mSize) == mRequestedSize); + MOZ_ASSERT(*uvec2::FromSize(mDefaultFB->mSize) == mRequestedSize); return true; } @@ -583,7 +586,7 @@ bool WebGLContext::EnsureDefaultFB() { mDefaultFB_IsInvalid = true; - const auto actualSize = *uvec2::From(mDefaultFB->mSize); + const auto actualSize = *uvec2::FromSize(mDefaultFB->mSize); if (actualSize != mRequestedSize) { GenerateWarning( "Requested size %ux%u was too large, but resize" @@ -1303,7 +1306,7 @@ uvec2 WebGLContext::DrawingBufferSize() { if (!EnsureDefaultFB()) return {}; - return *uvec2::From(mDefaultFB->mSize); + return *uvec2::FromSize(mDefaultFB->mSize); } bool WebGLContext::ValidateAndInitFB(const WebGLFramebuffer* const fb, @@ -1680,64 +1683,57 @@ void WebGLContext::ClearVRFrame() { #endif } +RefPtr WebGLContext::GetVRFrame() { + if (!gl) return nullptr; + + EnsureVRReady(); + UniquePtr* maybeVrScreen = nullptr; #if defined(MOZ_WIDGET_ANDROID) -already_AddRefed -WebGLContext::GetVRFrame() { - if (!gl) return nullptr; + maybeVrScreen = &mVRScreen; +#endif + RefPtr sharedSurface; + if (maybeVrScreen) { + auto& vrScreen = *maybeVrScreen; + // Create a custom GLScreenBuffer for VR. + if (!vrScreen) { + auto caps = gl->Screen()->mCaps; + vrScreen = gl::GLScreenBuffer::Create(gl, gfx::IntSize(1, 1), caps); + } + MOZ_ASSERT(vrScreen); - EnsureVRReady(); + // Swap buffers as though composition has occurred. + // We will then share the resulting front buffer to be submitted to the VR + // compositor. + PresentScreenBuffer(vrScreen.get()); - // Create a custom GLScreenBuffer for VR. - if (!mVRScreen) { - auto caps = gl->Screen()->mCaps; - mVRScreen = GLScreenBuffer::Create(gl, gfx::IntSize(1, 1), caps); + if (IsContextLost()) return nullptr; + + sharedSurface = vrScreen->Front(); + if (!sharedSurface || !sharedSurface->Surf() || + !sharedSurface->Surf()->IsBufferAvailable()) + return nullptr; + + // Make sure that the WebGL buffer is committed to the attached + // SurfaceTexture on Android. + sharedSurface->Surf()->ProducerAcquire(); + sharedSurface->Surf()->Commit(); + sharedSurface->Surf()->ProducerRelease(); + } else { + /** + * Swap buffers as though composition has occurred. + * We will then share the resulting front buffer to be submitted to the VR + * compositor. + */ + PresentScreenBuffer(); + + gl::GLScreenBuffer* screen = gl->Screen(); + if (!screen) return nullptr; + + sharedSurface = screen->Front(); + if (!sharedSurface) return nullptr; } - - MOZ_ASSERT(mVRScreen); - - // Swap buffers as though composition has occurred. - // We will then share the resulting front buffer to be submitted to the VR - // compositor. - PresentScreenBuffer(mVRScreen.get()); - - if (IsContextLost()) return nullptr; - - RefPtr sharedSurface = mVRScreen->Front(); - if (!sharedSurface || !sharedSurface->Surf() || - !sharedSurface->Surf()->IsBufferAvailable()) - return nullptr; - - // Make sure that the WebGL buffer is committed to the attached SurfaceTexture - // on Android. - sharedSurface->Surf()->ProducerAcquire(); - sharedSurface->Surf()->Commit(); - sharedSurface->Surf()->ProducerRelease(); - - return sharedSurface.forget(); + return sharedSurface; } -#else -already_AddRefed -WebGLContext::GetVRFrame() { - if (!gl) return nullptr; - - EnsureVRReady(); - /** - * Swap buffers as though composition has occurred. - * We will then share the resulting front buffer to be submitted to the VR - * compositor. - */ - PresentScreenBuffer(); - - gl::GLScreenBuffer* screen = gl->Screen(); - if (!screen) return nullptr; - - RefPtr sharedSurface = screen->Front(); - if (!sharedSurface) return nullptr; - - return sharedSurface.forget(); -} - -#endif // ifdefined(MOZ_WIDGET_ANDROID) void WebGLContext::EnsureVRReady() { if (mVRReady) { @@ -1756,12 +1752,18 @@ void WebGLContext::EnsureVRReady() { } auto factory = gl::GLScreenBuffer::CreateFactory(gl, caps, nullptr, flags); gl->Screen()->Morph(std::move(factory)); + + bool needsResize = false; #if defined(MOZ_WIDGET_ANDROID) // On Android we are using a different GLScreenBuffer for WebVR, so we need // a resize here because PresentScreenBuffer() may not be called for the // gl->Screen() after we set the new factory. - gl->Screen()->Resize(DrawingBufferSize()); + needsResize = true; #endif + if (needsResize) { + const auto& size = DrawingBufferSize(); + gl->Screen()->Resize({size.x, size.y}); + } mVRReady = true; } @@ -1772,7 +1774,7 @@ const char* WebGLContext::FuncName() const { if (MOZ_LIKELY(mFuncScope)) { ret = mFuncScope->mFuncName; } else { - MOZ_ASSERT(false); + MOZ_ASSERT(false, "FuncScope not on stack!"); ret = ""; } return ret; diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index d649c5b3ca6a..f2c0e4dfe2ae 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -436,10 +436,14 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr { nsCString text; text.AppendPrintf("WebGL warning: %s: ", FuncName()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat-security" +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wformat-security" +#endif text.AppendPrintf(fmt, args...); -#pragma clang diagnostic pop +#ifdef __clang__ +# pragma clang diagnostic pop +#endif GenerateErrorImpl(err, text); } @@ -612,7 +616,7 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr { void PixelStorei(GLenum pname, GLint param); void PolygonOffset(GLfloat factor, GLfloat units); - already_AddRefed GetVRFrame(); + RefPtr GetVRFrame(); void ClearVRFrame(); void EnsureVRReady(); @@ -1290,10 +1294,14 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr { nsCString msg; msg.AppendPrintf("WebGL perf warning: %s: ", funcName); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat-security" +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wformat-security" +#endif msg.AppendPrintf(fmt, args...); -#pragma clang diagnostic pop +#ifdef __clang__ +# pragma clang diagnostic pop +#endif GenerateErrorImpl(0, msg); diff --git a/dom/canvas/WebGLMethodDispatcher.h b/dom/canvas/WebGLMethodDispatcher.h index 57c5e13ce7f9..d7fc1ea96835 100644 --- a/dom/canvas/WebGLMethodDispatcher.h +++ b/dom/canvas/WebGLMethodDispatcher.h @@ -53,6 +53,7 @@ DEFINE_ASYNC(HostWebGLContext::DeleteVertexArray) DEFINE_ASYNC(HostWebGLContext::ClearVRFrame) DEFINE_SYNC(HostWebGLContext::GetSurfaceSnapshot) +DEFINE_SYNC(HostWebGLContext::GetVRFrame) DEFINE_ASYNC(HostWebGLContext::Disable) DEFINE_ASYNC(HostWebGLContext::Enable) diff --git a/dom/canvas/WebGLParent.cpp b/dom/canvas/WebGLParent.cpp index 71400b8d9443..aa17439a9320 100644 --- a/dom/canvas/WebGLParent.cpp +++ b/dom/canvas/WebGLParent.cpp @@ -134,7 +134,7 @@ mozilla::ipc::IPCResult WebGLParent::RecvUpdateCompositableHandle( return IPC_OK(); } -already_AddRefed WebGLParent::GetVRFrame() { +RefPtr WebGLParent::GetVRFrame() { if (!mHost) { return nullptr; } diff --git a/dom/canvas/WebGLParent.h b/dom/canvas/WebGLParent.h index 154b15f02bdc..51abf691ea12 100644 --- a/dom/canvas/WebGLParent.h +++ b/dom/canvas/WebGLParent.h @@ -32,7 +32,7 @@ class WebGLParent final : public PWebGLParent, static RefPtr Create(const webgl::InitContextDesc&, webgl::InitContextResult* out); - already_AddRefed GetVRFrame(); + RefPtr GetVRFrame(); private: WebGLParent(); diff --git a/dom/canvas/WebGLTypes.h b/dom/canvas/WebGLTypes.h index e6c4c411088d..90041305e348 100644 --- a/dom/canvas/WebGLTypes.h +++ b/dom/canvas/WebGLTypes.h @@ -414,8 +414,8 @@ struct avec2 { static auto From(const U& val) { return From(val.x, val.y); } - template <> - static auto From(const gfx::IntSize& val) { + template + static auto FromSize(const U& val) { return From(val.width, val.height); } @@ -528,8 +528,8 @@ struct Limits final { uint32_t maxTexCubeSize = 0; uint32_t maxVertexAttribs = 0; std::array maxViewportDims = {}; - std::array pointSizeRange = {1, 1}; - std::array lineWidthRange = {1, 1}; + std::array pointSizeRange = {{1, 1}}; + std::array lineWidthRange = {{1, 1}}; // WebGL 2 uint32_t maxTexArrayLayers = 0; diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build index adcafecf38a8..294d7a7fb20b 100644 --- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -213,3 +213,6 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc'): if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CXXFLAGS += ['-Werror=implicit-int-conversion'] + +if CONFIG['CC_TYPE'] == 'gcc': + CXXFLAGS += ['-Wno-error=unused-result'] # GCC doesn't ignore (void)MustUse(); diff --git a/dom/canvas/test/webgl-conf/generated-mochitest.ini b/dom/canvas/test/webgl-conf/generated-mochitest.ini index cb8c5882ffa4..cd95a544d814 100644 --- a/dom/canvas/test/webgl-conf/generated-mochitest.ini +++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini @@ -12100,7 +12100,7 @@ subsuite = webgl1-core subsuite = webgl1-core [generated/test_conformance__rendering__blending.html] subsuite = webgl1-core -fail-if = (os == 'android') || (os == 'linux') +fail-if = (os == 'android') [generated/test_conformance__rendering__canvas-alpha-bug.html] subsuite = webgl1-core [generated/test_conformance__rendering__clear-after-copyTexImage2D.html] diff --git a/dom/canvas/test/webgl-conf/mochitest-errata.ini b/dom/canvas/test/webgl-conf/mochitest-errata.ini index 2b5a2e648b32..2c4b89d08261 100644 --- a/dom/canvas/test/webgl-conf/mochitest-errata.ini +++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini @@ -803,7 +803,7 @@ fail-if = (os == 'linux') fail-if = (os == 'linux') [generated/test_conformance__rendering__blending.html] # Expected [1000,1,1,1], was [1,1,1,1] -fail-if = (os == 'android') || (os == 'linux') +fail-if = (os == 'android') [generated/test_2_conformance__rendering__blending.html] fail-if = (os == 'android') [generated/test_2_conformance2__glsl3__valid-invariant.html] diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 42ee3202aa15..2b1fe17e871a 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -806,9 +806,13 @@ void HTMLCanvasElement::ToBlob(JSContext* aCx, BlobCallback& aCallback, CanvasRenderingContextHelper::ToBlob(aCx, global, aCallback, aType, aParams, usePlaceholder, aRv); } - +#define DISABLE_OFFSCREEN_CANVAS 1 OffscreenCanvas* HTMLCanvasElement::TransferControlToOffscreen( ErrorResult& aRv) { + if (DISABLE_OFFSCREEN_CANVAS) { + aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); + return nullptr; + } if (mCurrentContext) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp index ae729c6dac4d..053bde082da8 100644 --- a/gfx/gl/GLBlitHelper.cpp +++ b/gfx/gl/GLBlitHelper.cpp @@ -729,6 +729,7 @@ bool GLBlitHelper::BlitImageToFramebuffer(layers::Image* const srcImage, case ImageFormat::TEXTURE_WRAPPER: return false; // todo } + return false; } // ------------------------------------- diff --git a/gfx/vr/ipc/PVRLayer.ipdl b/gfx/vr/ipc/PVRLayer.ipdl index 3e3d7fe0c6bc..5c73ccff2cba 100644 --- a/gfx/vr/ipc/PVRLayer.ipdl +++ b/gfx/vr/ipc/PVRLayer.ipdl @@ -7,7 +7,6 @@ include LayersSurfaces; include protocol PVRManager; -include protocol PWebGL; using mozilla::gfx::Rect from "mozilla/gfx/Rect.h"; @@ -19,11 +18,9 @@ async protocol PVRLayer manager PVRManager; parent: - async SubmitFrame(PWebGL webgl, uint64_t aFrameId, uint64_t aLastFrameId, + async SubmitFrame(SurfaceDescriptor aTexture, uint64_t aFrameId, Rect aLeftEyeRect, Rect aRightEyeRect); - async ClearSurfaces(); - async Destroy(); child: diff --git a/gfx/vr/ipc/VRLayerChild.cpp b/gfx/vr/ipc/VRLayerChild.cpp index 0f73c348ec5f..d0d3afcb5b6c 100644 --- a/gfx/vr/ipc/VRLayerChild.cpp +++ b/gfx/vr/ipc/VRLayerChild.cpp @@ -5,11 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "VRLayerChild.h" - #include "gfxPlatform.h" +#include "GLScreenBuffer.h" #include "../../../dom/canvas/ClientWebGLContext.h" +#include "mozilla/layers/TextureClientSharedSurface.h" +#include "SharedSurface.h" // for SharedSurface +#include "SharedSurfaceGL.h" // for SharedSurface +#include "mozilla/layers/LayersMessages.h" // for TimedTexture +#include "nsICanvasRenderingContextInternal.h" #include "mozilla/dom/HTMLCanvasElement.h" -#include "mozilla/dom/WebGLChild.h" +#include "mozilla/layers/SyncObject.h" // for SyncObjectClient namespace mozilla { namespace gfx { @@ -45,30 +50,69 @@ void VRLayerChild::SubmitFrame(const VRDisplayInfo& aDisplayInfo) { return; } + const auto& webgl = mCanvasElement->GetWebGLContext(); + if (!webgl) return; + + // Keep the SharedSurfaceTextureClient alive long enough for + // 1 extra frame, accomodating overlapped asynchronous rendering. + mLastFrameTexture = mThisFrameTexture; + +#if defined(MOZ_WIDGET_ANDROID) + /** + * Do not blit WebGL to a SurfaceTexture until the last submitted frame is + * already processed and the new frame poses are ready. SurfaceTextures need + * to be released in the VR render thread in order to allow to be used again + * in the WebGLContext GLScreenBuffer producer. Not doing so causes some + * freezes, crashes or other undefined behaviour. + */ + if (!mThisFrameTexture || aDisplayInfo.mDisplayState.lastSubmittedFrameId == + mLastSubmittedFrameId) { + mThisFrameTexture = webgl->GetVRFrame(); + } +#else + mThisFrameTexture = webgl->GetVRFrame(); +#endif // defined(MOZ_WIDGET_ANDROID) + mLastSubmittedFrameId = frameId; - const auto webgl = mCanvasElement->GetWebGLContext(); - if (!webgl) { + if (!mThisFrameTexture) { return; } - const auto webglChild = webgl->GetChild(); - if (!webglChild) { + VRManagerChild* vrmc = VRManagerChild::Get(); + layers::SyncObjectClient* syncObject = vrmc->GetSyncObject(); + mThisFrameTexture->SyncWithObject(syncObject); + if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { + if (syncObject && syncObject->IsSyncObjectValid()) { + syncObject->Synchronize(); + } + } + + gl::SharedSurface* surf = mThisFrameTexture->Surf(); + if (surf->mType == gl::SharedSurfaceType::Basic) { + gfxCriticalError() << "SharedSurfaceType::Basic not supported for WebVR"; return; } - SendSubmitFrame(webglChild, frameId, - aDisplayInfo.mDisplayState.lastSubmittedFrameId, mLeftEyeRect, - mRightEyeRect); + layers::SurfaceDescriptor desc; + if (!surf->ToSurfaceDescriptor(&desc)) { + gfxCriticalError() << "SharedSurface::ToSurfaceDescriptor failed in " + "VRLayerChild::SubmitFrame"; + return; + } + + SendSubmitFrame(desc, frameId, mLeftEyeRect, mRightEyeRect); } bool VRLayerChild::IsIPCOpen() { return mIPCOpen; } void VRLayerChild::ClearSurfaces() { - const auto webgl = mCanvasElement->GetWebGLContext(); + mThisFrameTexture = nullptr; + mLastFrameTexture = nullptr; + + const auto& webgl = mCanvasElement->GetWebGLContext(); if (webgl) { webgl->ClearVRFrame(); } - SendClearSurfaces(); } void VRLayerChild::ActorDestroy(ActorDestroyReason aWhy) { mIPCOpen = false; } diff --git a/gfx/vr/ipc/VRLayerChild.h b/gfx/vr/ipc/VRLayerChild.h index de13120c8001..5d156e713b5e 100644 --- a/gfx/vr/ipc/VRLayerChild.h +++ b/gfx/vr/ipc/VRLayerChild.h @@ -61,6 +61,9 @@ class VRLayerChild : public PVRLayerChild { gfx::Rect mLeftEyeRect; gfx::Rect mRightEyeRect; + RefPtr mThisFrameTexture; + RefPtr mLastFrameTexture; + uint64_t mLastSubmittedFrameId; }; diff --git a/gfx/vr/ipc/VRLayerParent.cpp b/gfx/vr/ipc/VRLayerParent.cpp index e8c7551021b8..c478a08275a8 100644 --- a/gfx/vr/ipc/VRLayerParent.cpp +++ b/gfx/vr/ipc/VRLayerParent.cpp @@ -5,12 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "VRLayerParent.h" - -#include "mozilla/dom/WebGLParent.h" -#include "mozilla/layers/CompositorThread.h" #include "mozilla/Unused.h" -#include "SharedSurface.h" -#include "SurfaceTypes.h" +#include "mozilla/layers/CompositorThread.h" namespace mozilla { using namespace layers; @@ -43,67 +39,15 @@ void VRLayerParent::Destroy() { } mozilla::ipc::IPCResult VRLayerParent::RecvSubmitFrame( - mozilla::dom::PWebGLParent* aPWebGLParent, const uint64_t& aFrameId, - const uint64_t& aLastFrameId, const gfx::Rect& aLeftEyeRect, - const gfx::Rect& aRightEyeRect) { - // Keep the SharedSurfaceTextureClient alive long enough for - // 1 extra frame, accomodating overlapped asynchronous rendering. - mLastFrameTexture = mThisFrameTexture; - - auto webGLParent = static_cast(aPWebGLParent); - if (!webGLParent) { - return IPC_OK(); - } - -#if defined(MOZ_WIDGET_ANDROID) - /** - * Do not blit WebGL to a SurfaceTexture until the last submitted frame is - * already processed and the new frame poses are ready. SurfaceTextures need - * to be released in the VR render thread in order to allow to be used again - * in the WebGLContext GLScreenBuffer producer. Not doing so causes some - * freezes, crashes or other undefined behaviour. - * DLP: TODO: Umm... not even the same process as before so... - */ - if (!mThisFrameTexture || aLastFrameId == mLastSubmittedFrameId) { - mThisFrameTexture = webGLParent->GetVRFrame(); - } -#else - mThisFrameTexture = webGLParent->GetVRFrame(); -#endif // defined(MOZ_WIDGET_ANDROID) - - if (!mThisFrameTexture) { - return IPC_OK(); - } - - // TODO: I killed all of the syncObject stuff rather than move it here - // cause my current understanding is that it isn't needed here. - - gl::SharedSurface* surf = mThisFrameTexture->Surf(); - if (surf->mType == gl::SharedSurfaceType::Basic) { - gfxCriticalError() << "SharedSurfaceType::Basic not supported for WebVR"; - return IPC_OK(); - } - - layers::SurfaceDescriptor desc; - if (!surf->ToSurfaceDescriptor(&desc)) { - gfxCriticalError() << "SharedSurface::ToSurfaceDescriptor failed in " - "VRLayerParent::SubmitFrame"; - return IPC_OK(); - } - + const layers::SurfaceDescriptor& aTexture, const uint64_t& aFrameId, + const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) { if (mVRDisplayID) { VRManager* vm = VRManager::Get(); - vm->SubmitFrame(this, desc, aFrameId, aLeftEyeRect, aRightEyeRect); + vm->SubmitFrame(this, aTexture, aFrameId, aLeftEyeRect, aRightEyeRect); } return IPC_OK(); } -mozilla::ipc::IPCResult VRLayerParent::RecvClearSurfaces() { - mThisFrameTexture = nullptr; - mLastFrameTexture = nullptr; - return IPC_OK(); -} - } // namespace gfx } // namespace mozilla diff --git a/gfx/vr/ipc/VRLayerParent.h b/gfx/vr/ipc/VRLayerParent.h index 73494a9f3f3a..2a5b00c6c01d 100644 --- a/gfx/vr/ipc/VRLayerParent.h +++ b/gfx/vr/ipc/VRLayerParent.h @@ -12,14 +12,8 @@ #include "mozilla/RefPtr.h" #include "mozilla/gfx/PVRLayerParent.h" #include "gfxVR.h" -#include "mozilla/layers/TextureClientSharedSurface.h" namespace mozilla { - -namespace dom { -class PWebGLParent; -} - namespace gfx { class VRLayerParent : public PVRLayerParent { @@ -28,14 +22,9 @@ class VRLayerParent : public PVRLayerParent { public: VRLayerParent(uint32_t aVRDisplayID, const uint32_t aGroup); virtual mozilla::ipc::IPCResult RecvSubmitFrame( - mozilla::dom::PWebGLParent* aPWebGLParent, const uint64_t& aFrameId, - const uint64_t& aLastFrameId, const gfx::Rect& aLeftEyeRect, - const gfx::Rect& aRightEyeRect) override; - - mozilla::ipc::IPCResult RecvClearSurfaces() override; - + const layers::SurfaceDescriptor& aTexture, const uint64_t& aFrameId, + const gfx::Rect& aLeftEyeRect, const gfx::Rect& aRightEyeRect) override; virtual mozilla::ipc::IPCResult RecvDestroy() override; - uint32_t GetDisplayID() const { return mVRDisplayID; } uint32_t GetGroup() const { return mGroup; } @@ -45,9 +34,6 @@ class VRLayerParent : public PVRLayerParent { virtual ~VRLayerParent(); void Destroy(); - RefPtr mThisFrameTexture; - RefPtr mLastFrameTexture; - bool mIPCOpen; uint32_t mVRDisplayID; diff --git a/gfx/vr/moz.build b/gfx/vr/moz.build index 527bb66033ee..8cd26992693a 100644 --- a/gfx/vr/moz.build +++ b/gfx/vr/moz.build @@ -40,8 +40,6 @@ UNIFIED_SOURCES += [ 'ipc/VRChild.cpp', 'ipc/VRGPUChild.cpp', 'ipc/VRGPUParent.cpp', - 'ipc/VRLayerChild.cpp', - 'ipc/VRLayerParent.cpp', 'ipc/VRManagerChild.cpp', 'ipc/VRManagerParent.cpp', 'ipc/VRParent.cpp', @@ -54,6 +52,8 @@ UNIFIED_SOURCES += [ ] SOURCES += [ + 'ipc/VRLayerChild.cpp', + 'ipc/VRLayerParent.cpp', 'VRManager.cpp', 'VRPuppetCommandBuffer.cpp', 'VRShMem.cpp' @@ -85,8 +85,8 @@ IPDL_SOURCES = [ # For now, only enable FxR CLH for Windows Nightly builds (BUG 1565349) if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['NIGHTLY_BUILD']: - XPCOM_MANIFESTS += [ - 'components.conf', + XPCOM_MANIFESTS += [ + 'components.conf', ] SOURCES += [ 'nsFxrCommandLineHandler.cpp',