Bug 1632249 - WebXR compositing fixes. r=imanol

Differential Revision: https://phabricator.services.mozilla.com/D78117
This commit is contained in:
Jeff Gilbert 2020-06-10 22:21:04 +00:00
Родитель 9b09e54345
Коммит 28d2828abe
11 изменённых файлов: 84 добавлений и 88 удалений

Просмотреть файл

@ -398,7 +398,17 @@ ReturnType ClientWebGLContext::Run(Args&&... aArgs) const {
// ------------------------- Composition, etc -------------------------
void ClientWebGLContext::OnBeforePaintTransaction() { Present(); }
void ClientWebGLContext::OnBeforePaintTransaction() {
const RefPtr<layers::ImageBridgeChild> imageBridge =
layers::ImageBridgeChild::GetSingleton();
auto texType = layers::TextureType::Unknown;
if (imageBridge) {
texType = layers::PreferredCanvasTextureType(*imageBridge);
}
Present(nullptr, texType);
}
void ClientWebGLContext::EndComposition() {
// Mark ourselves as no longer invalidated.
@ -407,43 +417,18 @@ void ClientWebGLContext::EndComposition() {
// -
namespace webgl {
void Present(ClientWebGLContext& webgl) { webgl.Present(); }
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(
ClientWebGLContext& webgl, layers::KnowsCompositor* const kc) {
auto texType = layers::TextureType::Unknown;
if (kc) {
texType = layers::PreferredCanvasTextureType(*kc);
}
return webgl.GetFrontBuffer(texType);
}
} // namespace webgl
// -
void ClientWebGLContext::Present() {
void ClientWebGLContext::Present(WebGLFramebufferJS* const fb,
const layers::TextureType type) {
if (!mIsCanvasDirty) return;
mIsCanvasDirty = false;
mFrontBufferDesc = nullptr;
mFrontBufferSnapshot = nullptr;
Run<RPROC(Present)>();
Run<RPROC(Present)>(fb ? fb->mId : 0, type);
}
Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
const layers::TextureType type) {
if (!mFrontBufferDesc) {
const auto desc = Run<RPROC(GetFrontBuffer)>(type);
if (desc) {
mFrontBufferDesc = MakeUnique<layers::SurfaceDescriptor>(*desc);
}
}
if (!mFrontBufferDesc) return Nothing();
return Some(*mFrontBufferDesc);
WebGLFramebufferJS* const fb, const layers::TextureType type) {
return Run<RPROC(GetFrontBuffer)>(fb ? fb->mId : 0, type);
}
// -
@ -620,9 +605,6 @@ ClientWebGLContext::SetDimensions(const int32_t signedWidth,
}
if (size == curSize) return NS_OK; // MUST skip no-op resize
if (mIsCanvasDirty) {
Present();
}
state.mDrawingBufferSize = Nothing();
Run<RPROC(Resize)>(size);

Просмотреть файл

@ -974,7 +974,6 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
layers::LayersBackend GetCompositorBackendType() const;
bool mCapturedFrameInvalidated = false;
UniquePtr<layers::SurfaceDescriptor> mFrontBufferDesc;
// -------------------------------------------------------------------------
// WebGLRenderingContext Basic Properties and Methods
@ -995,8 +994,9 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
}
void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
void Present();
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(layers::TextureType);
void Present(WebGLFramebufferJS*, layers::TextureType);
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebufferJS*,
layers::TextureType);
RefPtr<gfx::SourceSurface> GetFrontBufferSnapshot() override;
private:

Просмотреть файл

@ -317,7 +317,7 @@ class ClientWebGLExtensionExplicitPresent : public ClientWebGLExtensionBase {
AutoJsWarning("present: Extension is `invalidated`.");
return;
}
mContext->Present();
mContext->OnBeforePaintTransaction();
}
};

Просмотреть файл

@ -107,8 +107,8 @@ void HostWebGLContext::JsWarning(const std::string& text) const {
}
Maybe<layers::SurfaceDescriptor> HostWebGLContext::GetFrontBuffer(
const layers::TextureType t) const {
return mContext->GetFrontBuffer(t);
const ObjectId fb, const layers::TextureType t) const {
return mContext->GetFrontBuffer(AutoResolve(fb), t);
}
//////////////////////////////////////////////

Просмотреть файл

@ -184,9 +184,11 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
mContext->SetCompositableHost(compositableHost);
}
void Present() { return (void)mContext->Present(); }
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(
const layers::TextureType t) const;
void Present(const ObjectId fb, const layers::TextureType t) const {
return (void)mContext->Present(AutoResolve(fb), t);
}
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId fb,
layers::TextureType) const;
RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot() const {
return mContext->GetFrontBufferSnapshot();

Просмотреть файл

@ -942,32 +942,46 @@ bool WebGLContext::PresentInto(gl::SwapChain& swapChain) {
return true;
}
void WebGLContext::Present() {
void WebGLContext::Present(WebGLFramebuffer* const fb,
const layers::TextureType consumerType) {
const FuncScope funcScope(*this, "<Present>");
if (IsContextLost()) return;
mResolvedDefaultFB = nullptr;
if (!mSwapChain.mFactory) {
NS_WARNING("Failed to make an ideal SurfaceFactory.");
mSwapChain.mFactory = MakeUnique<gl::SurfaceFactory_Basic>(*gl);
auto swapChain = &mSwapChain;
if (fb) {
swapChain = &fb->mOpaqueSwapChain;
} else {
mResolvedDefaultFB = nullptr;
}
MOZ_ASSERT(mSwapChain.mFactory);
(void)PresentInto(mSwapChain);
if (!swapChain->mFactory) {
auto typedFactory = gl::SurfaceFactory::Create(gl, consumerType);
if (typedFactory) {
swapChain->mFactory = std::move(typedFactory);
}
}
if (!swapChain->mFactory) {
NS_WARNING("Failed to make an ideal SurfaceFactory.");
swapChain->mFactory = MakeUnique<gl::SurfaceFactory_Basic>(*gl);
}
MOZ_ASSERT(swapChain->mFactory);
(void)PresentInto(*swapChain);
}
Maybe<layers::SurfaceDescriptor> WebGLContext::GetFrontBuffer(
const layers::TextureType consumerType) {
if (mSwapChain.mFactory &&
mSwapChain.mFactory->mDesc.consumerType != consumerType) {
auto typedFactory = gl::SurfaceFactory::Create(gl, consumerType);
if (typedFactory) {
mSwapChain.mFactory = std::move(typedFactory);
}
WebGLFramebuffer* const fb, const layers::TextureType consumerType) {
auto swapChain = &mSwapChain;
if (fb) {
swapChain = &fb->mOpaqueSwapChain;
}
const auto& front = mSwapChain.FrontBuffer();
if (swapChain->mFactory &&
swapChain->mFactory->mDesc.consumerType != consumerType) {
swapChain->mFactory = nullptr; // Better luck next Present.
}
const auto& front = swapChain->FrontBuffer();
if (!front) return {};
return front->ToSurfaceDescriptor();

Просмотреть файл

@ -100,6 +100,7 @@ class MozFramebuffer;
namespace layers {
class CompositableHost;
class SurfaceDescriptor;
}
namespace webgl {
@ -484,9 +485,10 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
bool PresentInto(gl::SwapChain& swapChain);
public:
void Present();
void Present(WebGLFramebuffer*, layers::TextureType);
RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot();
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(layers::TextureType);
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*,
layers::TextureType);
void RunContextLossTimer();
void CheckForContextLoss();

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/WeakPtr.h"
#include "GLScreenBuffer.h"
#include "WebGLObjectModel.h"
#include "WebGLStrongTypes.h"
#include "WebGLTexture.h"
@ -138,6 +139,7 @@ class WebGLFramebuffer final : public WebGLContextBoundObject,
const GLuint mGLName;
bool mHasBeenBound = false;
const UniquePtr<gl::MozFramebuffer> mOpaque;
gl::SwapChain mOpaqueSwapChain;
bool mInOpaqueRAF = false;
private:

Просмотреть файл

@ -989,26 +989,6 @@ inline std::string ToString(const nsACString& text) {
return {text.BeginReading(), text.Length()};
}
// -
// ClientWebGLContext exports!
// (So that you don't need to include the mess that is ClientWebGLContext.h)
namespace gfx {
class SourceSurface;
} // namespace gfx
namespace layers {
class KnowsCompositor;
class SurfaceDescriptor;
} // namespace layers
namespace webgl {
void Present(ClientWebGLContext&);
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ClientWebGLContext&,
layers::KnowsCompositor*);
} // namespace webgl
// -
} // namespace mozilla

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "ClientWebGLContext.h"
#include "gfxUtils.h"
#include "GLScreenBuffer.h"
#include "nsICanvasRenderingContextInternal.h"
@ -122,7 +123,12 @@ void ShareableCanvasRenderer::UpdateCompositableClient() {
if (!webgl) return nullptr;
if (!forwarder) return nullptr;
const auto desc = webgl::GetFrontBuffer(*webgl, forwarder);
auto texType = layers::TextureType::Unknown;
if (forwarder) {
texType = layers::PreferredCanvasTextureType(*forwarder);
}
const auto desc = webgl->GetFrontBuffer(nullptr, texType);
if (!desc) return nullptr;
return GetFrontBufferFromDesc(*desc, flags);
};

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/LayersMessages.h" // for TimedTexture
#include "mozilla/layers/SyncObject.h" // for SyncObjectClient
#include "mozilla/StaticPrefs_webgl.h"
#include "ClientWebGLContext.h"
#include "gfxPlatform.h"
@ -40,6 +41,7 @@ void VRLayerChild::Initialize(dom::HTMLCanvasElement* aCanvasElement,
void VRLayerChild::SetXRFramebuffer(WebGLFramebufferJS* fb) {
mFramebuffer = fb;
}
static constexpr bool kIsAndroid =
#if defined(MOZ_WIDGET_ANDROID)
true;
@ -65,7 +67,6 @@ void VRLayerChild::SubmitFrame(const VRDisplayInfo& aDisplayInfo) {
// 1 extra frame, accomodating overlapped asynchronous rendering.
mLastFrameTextureDesc = mThisFrameTextureDesc;
bool forSeparateVrSwapChain = false;
bool getNewFrame = true;
if (kIsAndroid) {
/**
@ -75,17 +76,24 @@ void VRLayerChild::SubmitFrame(const VRDisplayInfo& aDisplayInfo) {
* in the WebGLContext GLScreenBuffer producer. Not doing so causes some
* freezes, crashes or other undefined behaviour.
*/
forSeparateVrSwapChain = true;
getNewFrame = (!mThisFrameTextureDesc ||
aDisplayInfo.mDisplayState.lastSubmittedFrameId ==
mLastSubmittedFrameId);
}
if (getNewFrame) {
webgl::Present(*webgl);
RefPtr<layers::ImageBridgeChild> imageBridge =
const RefPtr<layers::ImageBridgeChild> imageBridge =
layers::ImageBridgeChild::GetSingleton();
mThisFrameTextureDesc = webgl::GetFrontBuffer(*webgl, imageBridge);
auto texType = layers::TextureType::Unknown;
if (imageBridge) {
texType = layers::PreferredCanvasTextureType(*imageBridge);
}
if (kIsAndroid && StaticPrefs::webgl_enable_surface_texture()) {
texType = layers::TextureType::AndroidNativeWindow;
}
webgl->Present(mFramebuffer, texType);
mThisFrameTextureDesc = webgl->GetFrontBuffer(mFramebuffer, texType);
}
mLastSubmittedFrameId = frameId;