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
This commit is contained in:
Jeff Gilbert 2020-01-08 22:19:26 +00:00
parent 0dfd1a2a0d
commit f26e4d546b
23 changed files with 256 additions and 377 deletions

View File

@ -359,18 +359,13 @@ inline void DefaultOrVoid<void>() {
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<MethodType>::ReturnType,
size_t Id = WebGLMethodDispatcher::Id<MethodType, method>(),
typename... Args>
ReturnType ClientWebGLContext::Run(Args&&... aArgs) const {
template <typename MethodType, MethodType method, typename ReturnType,
size_t Id, typename... Args>
ReturnType RunOn(const ClientWebGLContext& context, Args&&... aArgs) {
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!mNotLost) return DefaultOrVoid<ReturnType>();
const auto& inProcessContext = mNotLost->inProcess;
context.mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return DefaultOrVoid<ReturnType>();
const auto& inProcessContext = notLost->inProcess;
if (inProcessContext) {
return ((inProcessContext.get())->*method)(std::forward<Args>(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 <typename MethodType, MethodType method, typename ReturnType,
typename... Args>
// template <
// typename MethodType, MethodType method,
// typename ReturnType, size_t Id,
// typename... Args>
ReturnType ClientWebGLContext::Run(Args&&... aArgs) const {
return RunOn<MethodType, method, ReturnType,
WebGLMethodDispatcher::Id<MethodType, method>(), Args...>(
*this, std::forward<Args>(aArgs)...);
}
// -------------------------------------------------------------------------
// Client-side helper methods. Dispatch to a Host method.
// -------------------------------------------------------------------------
@ -446,7 +455,12 @@ void ClientWebGLContext::EndComposition() {
void ClientWebGLContext::Present() { Run<RPROC(Present)>(); }
void ClientWebGLContext::ClearVRFrame() { Run<RPROC(ClearVRFrame)>(); }
void ClientWebGLContext::ClearVRFrame() const { Run<RPROC(ClearVRFrame)>(); }
RefPtr<layers::SharedSurfaceTextureClient> ClientWebGLContext::GetVRFrame()
const {
return Run<RPROC(GetVRFrame)>();
}
already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
nsDisplayListBuilder* builder, Layer* oldLayer, LayerManager* manager) {

View File

@ -171,12 +171,12 @@ class ContextGenerationInfo final {
std::vector<TypedQuad> mGenericVertexAttribs;
std::array<bool, 4> mColorWriteMask = {true, true, true, true};
std::array<bool, 4> mColorWriteMask = {{true, true, true, true}};
std::array<int32_t, 4> mScissor = {};
std::array<int32_t, 4> mViewport = {};
std::array<float, 4> mClearColor = {0, 0, 0, 0};
std::array<float, 4> mBlendColor = {0, 0, 0, 0};
std::array<float, 2> mDepthRange = {0, 1};
std::array<float, 4> mClearColor = {{0, 0, 0, 0}};
std::array<float, 4> mBlendColor = {{0, 0, 0, 0}};
std::array<float, 2> mDepthRange = {{0, 1}};
std::vector<GLenum> 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<layers::SharedSurfaceTextureClient> GetVRFrame() const;
void ClearVRFrame() const;
private:
const uvec2& DrawingBufferSize();
@ -2114,10 +2119,21 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
template <typename ReturnType>
friend struct WebGLClientDispatcher;
// 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,
size_t Id, typename... Args>
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 <typename MethodType, MethodType method,
// typename ReturnType = typename
// FunctionTypeTraits<MethodType>::ReturnType, size_t Id =
// WebGLMethodDispatcher::Id<MethodType, method>(), typename... Args>
// ReturnType Run(Args&&... aArgs) const;
template <
typename MethodType, MethodType method,
typename ReturnType = typename FunctionTypeTraits<MethodType>::ReturnType,
typename... Args>
ReturnType Run(Args&&... aArgs) const;
// -------------------------------------------------------------------------

View File

@ -100,6 +100,11 @@ void HostWebGLContext::JsWarning(const std::string& text) const {
(void)mOwnerData.outOfProcess->mParent.SendJsWarning(text);
}
RefPtr<layers::SharedSurfaceTextureClient> HostWebGLContext::GetVRFrame()
const {
return mContext->GetVRFrame();
}
//////////////////////////////////////////////
// Creation

View File

@ -130,12 +130,8 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
AutoResolveT(const HostWebGLContext& parent, const ObjectId id)
: mParent(parent), mId(id) {}
template <typename T>
T* As() const = delete;
#define _(X) \
template <> \
WebGL##X* As<WebGL##X>() 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<HostWebGLContext> {
#undef _
template <typename T>
MOZ_IMPLICIT operator T*() const {
return As<T>();
T* coercer = nullptr;
return As(coercer);
}
template <typename T>
MOZ_IMPLICIT operator const T*() const {
return As<T>();
T* coercer = nullptr;
return As(coercer);
}
};
AutoResolveT AutoResolve(const ObjectId id) const { return {*this, id}; }
template <typename T>
T* ById(const ObjectId id) const {
return AutoResolve(id).As<T>();
T* coercer = nullptr;
return AutoResolve(id).As(coercer);
}
// -------------------------------------------------------------------------
@ -183,7 +182,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
}
void Present() { mContext->Present(); }
void ClearVRFrame() { mContext->ClearVRFrame(); }
void ClearVRFrame() const { mContext->ClearVRFrame(); }
Maybe<ICRData> InitializeCanvasRenderer(layers::LayersBackend backend) {
return mContext->InitializeCanvasRenderer(backend);
@ -782,9 +781,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
// Etc
public:
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame() const {
return mContext->GetVRFrame();
}
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame() const;
protected:
WebGL2Context* GetWebGL2Context() const {

View File

@ -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.

View File

@ -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 <type_traits>
// 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 <typename Derived, typename SinkType>
struct FunctionDispatcher;
template <typename Derived, typename SinkType>
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 <typename ReturnType, typename... Args>
bool DispatchAsyncFunction(ReturnType (*aFunc)(Args...)) {
std::tuple<typename RemoveCV<typename RemoveReference<Args>::Type>::Type...>
args;
if (!ReadArgs(args)) {
return false;
}
CallFunction(aFunc, args, std::index_sequence_for<Args...>{});
return true;
}
// void return value, non-const method variant
template <typename T, typename... Args>
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 <typename... Args>
bool DispatchAsyncFunction(void (*aFunc)(Args...)) {
std::tuple<typename RemoveCV<typename RemoveReference<Args>::Type>::Type...>
args;
if (!ReadArgs(args)) {
return false;
}
CallVoidFunction(aFunc, args, std::index_sequence_for<Args...>{});
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<size_t, 0>) {
return PcqStatus::Success;
}
template <typename T, typename MethodType, typename... Args,
size_t... Indices,
typename ReturnType =
typename mozilla::FunctionTypeTraits<MethodType>::ReturnType>
ReturnType CallMethod(T& aObj, MethodType aMethod, std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
size_t... Indices, typename ReturnType>
std::result_of<MethodType> CallMethod(T& aObj, MethodType aMethod,
std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
return (aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
template <typename FunctionType, typename... Args, size_t... Indices,
typename ReturnType =
typename mozilla::FunctionTypeTraits<FunctionType>::ReturnType>
ReturnType CallFunction(FunctionType aFunc, std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
return (*aFunc)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
template <typename T, typename MethodType, typename... Args,
size_t... Indices>
void CallVoidMethod(T& aObj, MethodType aMethod, std::tuple<Args...>& aArgs,
@ -306,12 +271,6 @@ class CommandSink : public BasicSink {
(aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
template <typename FunctionType, typename... Args, size_t... Indices>
void CallVoidFunction(FunctionType aFunc, std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
(*aFunc)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
template <typename... Args>
bool ReadArgs(std::tuple<Args...>& aArgs) {
PcqStatus status = CallTryRemove(aArgs, std::index_sequence_for<Args...>{});
@ -477,21 +436,6 @@ class SyncCommandSink : public CommandSink<Command> {
}
#endif
template <typename ReturnType, typename... Args>
bool DispatchSyncFunction(ReturnType (*aFunc)(Args...)) {
std::tuple<typename RemoveCV<typename RemoveReference<Args>::Type>::Type...>
args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
ReturnType response =
BaseType::CallFunction(aFunc, args, std::index_sequence_for<Args...>{});
return WriteACK(response);
}
// __cdecl/__thiscall non-const void method variant
template <typename T, typename... Args>
bool DispatchSyncMethod(T& aObj, void SINK_FCN_CC (T::*aMethod)(Args...)) {
@ -556,19 +500,6 @@ class SyncCommandSink : public CommandSink<Command> {
}
#endif
template <typename... Args>
bool DispatchSyncFunction(void (*aFunc)(Args...)) {
std::tuple<typename RemoveCV<typename RemoveReference<Args>::Type>::Type...>
args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
BaseType::CallVoidFunction(aFunc, args, std::index_sequence_for<Args...>{});
return WriteACK();
}
protected:
template <typename... Args>
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 <typename Derived, typename _SinkType>
struct FunctionDispatcher {
using SinkType = _SinkType;
template <CommandSyncType syncType>
struct DispatchFunction;
// Specialization for dispatching asynchronous functions
template <>
struct DispatchFunction<CommandSyncType::ASYNC> {
template <typename FunctionType>
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, FunctionType function) {
return aSink.DispatchAsyncFunction(function);
}
};
// Specialization for dispatching synchronous functions
template <>
struct DispatchFunction<CommandSyncType::SYNC> {
template <typename FunctionType>
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 <CommandSyncType syncType>
struct DispatchMethod;
/*
// Specialization for dispatching asynchronous methods
template <CommandSyncType SyncType>
struct DispatchMethod {
template <typename MethodType, typename ObjectType>
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType mMethod,
ObjectType& aObj) {
return aSink.DispatchMethod<SyncType>(aObj, mMethod);
}
};
// Specialization for dispatching asynchronous methods
template <>
struct DispatchMethod<CommandSyncType::ASYNC> {
template <typename MethodType, typename ObjectType>
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<CommandSyncType::SYNC> {
template <typename MethodType, typename ObjectType>
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<CommandSyncType::SYNC> {
template <typename MethodType, typename ObjectType>
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 <size_t commandId = 0> \
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId) { \
MOZ_ASSERT_UNREACHABLE("Unhandled command ID"); \
return false; \
} \
template <size_t commandId> \
static MOZ_ALWAYS_INLINE bool Dispatch(SinkType& aSink); \
template <size_t commandId> \
struct FuncInfo; \
template <size_t commandId> \
static constexpr CommandSyncType SyncType(); \
template <typename FuncType, FuncType func> \
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<decltype(&_FUNC), &_FUNC>() { \
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

View File

@ -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, "<Create>");
if (mOptions.antialias && !StaticPrefs::webgl_msaa_force()) {
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
@ -311,6 +312,8 @@ static bool HasAcceleratedLayers(const nsCOMPtr<nsIGfxInfo>& gfxInfo) {
bool WebGLContext::CreateAndInitGL(
bool forceEnabled, std::vector<FailureReason>* const out_failReasons) {
const FuncScope funcScope(*this, "<Create>");
// 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<layers::SharedSurfaceTextureClient> WebGLContext::GetVRFrame() {
if (!gl) return nullptr;
EnsureVRReady();
UniquePtr<gl::GLScreenBuffer>* maybeVrScreen = nullptr;
#if defined(MOZ_WIDGET_ANDROID)
already_AddRefed<layers::SharedSurfaceTextureClient>
WebGLContext::GetVRFrame() {
if (!gl) return nullptr;
maybeVrScreen = &mVRScreen;
#endif
RefPtr<layers::SharedSurfaceTextureClient> 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<SharedSurfaceTextureClient> 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<layers::SharedSurfaceTextureClient>
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<layers::SharedSurfaceTextureClient> 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 = "<funcName unknown>";
}
return ret;

View File

@ -436,10 +436,14 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
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<WebGLContext> {
void PixelStorei(GLenum pname, GLint param);
void PolygonOffset(GLfloat factor, GLfloat units);
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame();
void ClearVRFrame();
void EnsureVRReady();
@ -1290,10 +1294,14 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
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);

View File

@ -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)

View File

@ -134,7 +134,7 @@ mozilla::ipc::IPCResult WebGLParent::RecvUpdateCompositableHandle(
return IPC_OK();
}
already_AddRefed<layers::SharedSurfaceTextureClient> WebGLParent::GetVRFrame() {
RefPtr<layers::SharedSurfaceTextureClient> WebGLParent::GetVRFrame() {
if (!mHost) {
return nullptr;
}

View File

@ -32,7 +32,7 @@ class WebGLParent final : public PWebGLParent,
static RefPtr<WebGLParent> Create(const webgl::InitContextDesc&,
webgl::InitContextResult* out);
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame();
private:
WebGLParent();

View File

@ -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 <typename U>
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<uint32_t, 2> maxViewportDims = {};
std::array<float, 2> pointSizeRange = {1, 1};
std::array<float, 2> lineWidthRange = {1, 1};
std::array<float, 2> pointSizeRange = {{1, 1}};
std::array<float, 2> lineWidthRange = {{1, 1}};
// WebGL 2
uint32_t maxTexArrayLayers = 0;

View File

@ -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();

View File

@ -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]

View File

@ -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]

View File

@ -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;

View File

@ -729,6 +729,7 @@ bool GLBlitHelper::BlitImageToFramebuffer(layers::Image* const srcImage,
case ImageFormat::TEXTURE_WRAPPER:
return false; // todo
}
return false;
}
// -------------------------------------

View File

@ -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:

View File

@ -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; }

View File

@ -61,6 +61,9 @@ class VRLayerChild : public PVRLayerChild {
gfx::Rect mLeftEyeRect;
gfx::Rect mRightEyeRect;
RefPtr<layers::SharedSurfaceTextureClient> mThisFrameTexture;
RefPtr<layers::SharedSurfaceTextureClient> mLastFrameTexture;
uint64_t mLastSubmittedFrameId;
};

View File

@ -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<mozilla::dom::WebGLParent*>(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

View File

@ -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<layers::SharedSurfaceTextureClient> mThisFrameTexture;
RefPtr<layers::SharedSurfaceTextureClient> mLastFrameTexture;
bool mIPCOpen;
uint32_t mVRDisplayID;

View File

@ -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'