Bug 1317774 - Add gfx code needed to use WebRender in gecko. r=gfx

The overall architecture here is that we add a new layers type, LAYERS_WR,
which can be used in place of client layers. The WebRenderLayerManager, in
the EndTransaction call, paints content into images and ships them over the
PWebRenderBridge to the compositor thread. The WebRenderBridgeParent code on
the compositor side talks to WebRender via the API in webrender.h.

MozReview-Commit-ID: JKLTLJWVXiN
This commit is contained in:
Mozilla Graphics Team
2016-11-16 08:54:51 -05:00
parent 6f7d6c416d
commit 8d165b3b75
34 changed files with 1738 additions and 0 deletions

View File

@@ -194,6 +194,10 @@ static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel[] = {
NSOpenGLPFAAccelerated,
NSOpenGLPFAAllowOfflineRenderers,
NSOpenGLPFADoubleBuffer,
#ifdef MOZ_ENABLE_WEBRENDER
NSOpenGLPFAOpenGLProfile,
NSOpenGLProfileVersion3_2Core,
#endif
0
};

View File

@@ -1133,7 +1133,12 @@ CreateForWidget(Display* aXDisplay, Window aXWindow, bool aForceAccelerated)
RefPtr<GLContextGLX> gl = GLContextGLX::CreateGLContext(CreateContextFlags::NONE,
caps, shareContext, false,
aXDisplay, aXWindow, config,
#ifdef MOZ_ENABLE_WEBRENDER
//TODO: we might want to pass an additional bool to select GL core/compat
false, nullptr, ContextProfile::OpenGLCore); //WR: required GL 3.2+
#else
false);
#endif
return gl.forget();
}

View File

@@ -97,6 +97,7 @@ class SpecificLayerAttributes;
class Compositor;
class FrameUniformityData;
class PersistentBufferProvider;
class WebRenderLayerManager;
namespace layerscope {
class LayersPacket;
@@ -200,6 +201,9 @@ public:
virtual BasicLayerManager* AsBasicLayerManager()
{ return nullptr; }
virtual WebRenderLayerManager* AsWebRenderLayerManager()
{ return nullptr; }
/**
* Returns true if this LayerManager is owned by an nsIWidget,
* and is used for drawing into the widget.

View File

@@ -45,6 +45,7 @@ enum class LayersBackend : int8_t {
LAYERS_D3D9,
LAYERS_D3D11,
LAYERS_CLIENT,
LAYERS_WR,
LAYERS_LAST
};

View File

@@ -20,6 +20,7 @@
#include "mozilla/layers/PLayerTransactionChild.h"
#include "mozilla/layers/TextureClient.h"// for TextureClient
#include "mozilla/layers/TextureClientPool.h"// for TextureClientPool
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
@@ -1144,6 +1145,22 @@ CompositorBridgeChild::HandleFatalError(const char* aName, const char* aMsg) con
dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
}
PWebRenderBridgeChild*
CompositorBridgeChild::AllocPWebRenderBridgeChild(const uint64_t& aPipelineId)
{
WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId);
child->AddRef();
return child;
}
bool
CompositorBridgeChild::DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor)
{
WebRenderBridgeChild* child = static_cast<WebRenderBridgeChild*>(aActor);
child->Release();
return true;
}
} // namespace layers
} // namespace mozilla

View File

@@ -228,6 +228,9 @@ public:
void WillEndTransaction();
PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const uint64_t& aPipelineId) override;
bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor) override;
private:
// Private destructor, to discourage deletion outside of Release():
virtual ~CompositorBridgeChild();

View File

@@ -49,6 +49,7 @@
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/PLayerTransactionParent.h"
#include "mozilla/layers/RemoteContentController.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
#include "mozilla/mozalloc.h" // for operator new, etc
@@ -1839,6 +1840,45 @@ CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
return IPC_OK();
}
PWebRenderBridgeParent*
CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId)
{
#ifndef MOZ_ENABLE_WEBRENDER
// Extra guard since this in the parent process and we don't want a malicious
// child process invoking this codepath before it's ready
MOZ_RELEASE_ASSERT(false);
#endif
MOZ_ASSERT(aPipelineId == mRootLayerTreeID);
RefPtr<gl::GLContext> glc(gl::GLContextProvider::CreateForCompositorWidget(mWidget, true));
WebRenderBridgeParent* parent = new WebRenderBridgeParent(aPipelineId, mWidget, glc.get(), nullptr);
parent->AddRef(); // IPDL reference
MonitorAutoLock lock(*sIndirectLayerTreesLock);
MOZ_ASSERT(sIndirectLayerTrees[aPipelineId].mWRBridge == nullptr);
sIndirectLayerTrees[aPipelineId].mWRBridge = parent;
return parent;
}
bool
CompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor)
{
#ifndef MOZ_ENABLE_WEBRENDER
// Extra guard since this in the parent process and we don't want a malicious
// child process invoking this codepath before it's ready
MOZ_RELEASE_ASSERT(false);
#endif
WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
auto it = sIndirectLayerTrees.find(parent->PipelineId());
if (it != sIndirectLayerTrees.end()) {
it->second.mWRBridge = nullptr;
}
}
parent->Release(); // IPDL reference
return true;
}
static void
EraseLayerState(uint64_t aId)
{

View File

@@ -69,6 +69,7 @@ class PAPZParent;
class CrossProcessCompositorBridgeParent;
class CompositorThreadHolder;
class InProcessCompositorSession;
class WebRenderBridgeParent;
struct ScopedLayerTreeRegistration
{
@@ -444,6 +445,7 @@ public:
APZCTreeManagerParent* mApzcTreeManagerParent;
CompositorBridgeParent* mParent;
LayerManagerComposite* mLayerManager;
RefPtr<WebRenderBridgeParent> mWRBridge;
// Pointer to the CrossProcessCompositorBridgeParent. Used by APZCs to share
// their FrameMetrics with the corresponding child process that holds
// the PCompositorBridgeChild
@@ -537,6 +539,9 @@ public:
return !!mApzcTreeManager;
}
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const uint64_t& aPipelineId) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
private:
void Initialize();

View File

@@ -48,6 +48,7 @@
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/PLayerTransactionParent.h"
#include "mozilla/layers/RemoteContentController.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
#include "mozilla/mozalloc.h" // for operator new, etc
@@ -246,6 +247,54 @@ CrossProcessCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
return true;
}
PWebRenderBridgeParent*
CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId)
{
#ifndef MOZ_ENABLE_WEBRENDER
// Extra guard since this in the parent process and we don't want a malicious
// child process invoking this codepath before it's ready
MOZ_RELEASE_ASSERT(false);
#endif
// Check to see if this child process has access to this layer tree.
if (!LayerTreeOwnerTracker::Get()->IsMapped(aPipelineId, OtherPid())) {
NS_ERROR("Unexpected layers id in AllocPAPZCTreeManagerParent; dropping message...");
return nullptr;
}
MonitorAutoLock lock(*sIndirectLayerTreesLock);
MOZ_ASSERT(sIndirectLayerTrees.find(aPipelineId) != sIndirectLayerTrees.end());
MOZ_ASSERT(sIndirectLayerTrees[aPipelineId].mWRBridge == nullptr);
CompositorBridgeParent* cbp = sIndirectLayerTrees[aPipelineId].mParent;
WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWRBridge.get();
WebRenderBridgeParent* parent = new WebRenderBridgeParent(
aPipelineId, nullptr, root->GLContext(), root->WindowState());
parent->AddRef(); // IPDL reference
sIndirectLayerTrees[aPipelineId].mWRBridge = parent;
return parent;
}
bool
CrossProcessCompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor)
{
#ifndef MOZ_ENABLE_WEBRENDER
// Extra guard since this in the parent process and we don't want a malicious
// child process invoking this codepath before it's ready
MOZ_RELEASE_ASSERT(false);
#endif
WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
auto it = sIndirectLayerTrees.find(parent->PipelineId());
if (it != sIndirectLayerTrees.end()) {
it->second.mWRBridge = nullptr;
}
}
parent->Release(); // IPDL reference
return true;
}
mozilla::ipc::IPCResult
CrossProcessCompositorBridgeParent::RecvNotifyChildCreated(const uint64_t& child)
{

View File

@@ -153,6 +153,9 @@ public:
virtual void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) override;
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const uint64_t& aPipelineId) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
protected:
void OnChannelConnected(int32_t pid) override {
mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();

View File

@@ -17,6 +17,7 @@ include protocol PImageContainer;
include protocol PLayer;
include protocol PLayerTransaction;
include protocol PTexture;
include protocol PWebRenderBridge;
include "mozilla/GfxMessageUtils.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
@@ -53,6 +54,7 @@ sync protocol PCompositorBridge
manages PLayerTransaction;
manages PTexture;
manages PCompositorWidget;
manages PWebRenderBridge;
child:
// The child should invalidate retained layers. This is used for local
@@ -228,6 +230,9 @@ parent:
sync SyncWithCompositor();
// The pipelineId is the same as the layersId
async PWebRenderBridge(uint64_t pipelineId);
child:
// Send back Compositor Frame Metrics from APZCs so tiled layers can
// update progressively.

View File

@@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 "mozilla/GfxMessageUtils.h";
include protocol PCompositorBridge;
using WRImageFormat from "webrender.h";
using WRImageKey from "webrender.h";
using WRRect from "webrender.h";
using MaybeImageMask from "mozilla/layers/WebRenderTypes.h";
using mozilla::gfx::ByteBuffer from "mozilla/layers/WebRenderTypes.h";
using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
namespace mozilla {
namespace layers {
sync protocol PWebRenderBridge
{
manager PCompositorBridge;
parent:
sync Create(uint32_t aWidth, uint32_t aHeight);
sync Destroy();
sync AddImage(uint32_t aWidth, uint32_t aHeight, uint32_t aStride,
WRImageFormat aFormat, ByteBuffer aBytes)
returns (WRImageKey aOutImageKey);
sync UpdateImage(WRImageKey aImageKey, uint32_t aWidth, uint32_t aHeight,
WRImageFormat aFormat, ByteBuffer aBytes);
sync DeleteImage(WRImageKey aImageKey);
sync PushDLBuilder();
sync PopDLBuilder(WRRect aBounds, WRRect aOverflow, Matrix4x4 aMatrix,
uint64_t aScrollId);
sync DPBegin(uint32_t aWidth, uint32_t aHeight)
returns (bool aOutSuccess);
sync DPEnd();
sync DPPushRect(WRRect aBounds, WRRect aClip, float r, float g, float b, float a);
sync DPPushImage(WRRect aBounds, WRRect aClip, MaybeImageMask aMask, WRImageKey aKey);
sync DPPushIframe(WRRect aBounds, WRRect aClip, uint64_t aLayersId);
async __delete__();
};
} // layers
} // mozilla

View File

@@ -202,6 +202,10 @@ EXPORTS.mozilla.layers += [
'RenderTrace.h',
'TextureWrapperImage.h',
'TransactionIdAllocator.h',
'wr/WebRenderBridgeChild.h',
'wr/WebRenderBridgeParent.h',
'wr/WebRenderLayerManager.h',
'wr/WebRenderTypes.h',
]
if CONFIG['MOZ_X11']:
@@ -372,6 +376,14 @@ UNIFIED_SOURCES += [
'RenderTrace.cpp',
'RotatedBuffer.cpp',
'TextureWrapperImage.cpp',
'wr/WebRenderBridgeChild.cpp',
'wr/WebRenderBridgeParent.cpp',
'wr/WebRenderCanvasLayer.cpp',
'wr/WebRenderColorLayer.cpp',
'wr/WebRenderContainerLayer.cpp',
'wr/WebRenderImageLayer.cpp',
'wr/WebRenderLayerManager.cpp',
'wr/WebRenderPaintedLayer.cpp',
]
SOURCES += [
@@ -413,6 +425,7 @@ IPDL_SOURCES = [
'ipc/PLayerTransaction.ipdl',
'ipc/PTexture.ipdl',
'ipc/PVideoBridge.ipdl',
'ipc/PWebRenderBridge.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et 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 "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
namespace mozilla {
namespace layers {
WebRenderBridgeChild::WebRenderBridgeChild(const uint64_t& aPipelineId)
{
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et 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 mozilla_layers_WebRenderBridgeChild_h
#define mozilla_layers_WebRenderBridgeChild_h
#include "mozilla/layers/PWebRenderBridgeChild.h"
namespace mozilla {
namespace widget {
class CompositorWidget;
}
namespace layers {
class WebRenderBridgeParent;
class WebRenderBridgeChild final : public PWebRenderBridgeChild
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild)
public:
explicit WebRenderBridgeChild(const uint64_t& aPipelineId);
protected:
~WebRenderBridgeChild() {}
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_WebRenderBridgeChild_h

View File

@@ -0,0 +1,199 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et 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 "mozilla/layers/WebRenderBridgeParent.h"
#include "GLContext.h"
#include "GLContextProvider.h"
#include "mozilla/widget/CompositorWidget.h"
namespace mozilla {
namespace layers {
WebRenderBridgeParent::WebRenderBridgeParent(const uint64_t& aPipelineId,
widget::CompositorWidget* aWidget,
gl::GLContext* aGlContext,
wrwindowstate* aWrWindowState)
: mPipelineId(aPipelineId)
, mWidget(aWidget)
, mWRState(nullptr)
, mGLContext(aGlContext)
, mWRWindowState(aWrWindowState)
{
MOZ_ASSERT(mGLContext);
if (!mWRWindowState) {
// mWRWindowState should only be null for the root WRBP of a layers tree,
// i.e. the one created by the CompositorBridgeParent as opposed to the
// CrossProcessCompositorBridgeParent
MOZ_ASSERT(mWidget);
mWRWindowState = wr_init_window(mPipelineId);
}
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvCreate(const uint32_t& aWidth,
const uint32_t& aHeight)
{
if (mWRState) {
return IPC_OK();
}
MOZ_ASSERT(mWRWindowState);
mGLContext->MakeCurrent();
mWRState = wr_create(mWRWindowState, aWidth, aHeight, mPipelineId);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDestroy()
{
MOZ_ASSERT(mWRState);
wr_destroy(mWRState);
mWRState = nullptr;
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvAddImage(const uint32_t& aWidth,
const uint32_t& aHeight,
const uint32_t& aStride,
const WRImageFormat& aFormat,
const ByteBuffer& aBuffer,
WRImageKey* aOutImageKey)
{
MOZ_ASSERT(mWRWindowState);
*aOutImageKey = wr_add_image(mWRWindowState, aWidth, aHeight, aStride, aFormat,
aBuffer.mData, aBuffer.mLength);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvUpdateImage(const WRImageKey& aImageKey,
const uint32_t& aWidth,
const uint32_t& aHeight,
const WRImageFormat& aFormat,
const ByteBuffer& aBuffer)
{
MOZ_ASSERT(mWRWindowState);
wr_update_image(mWRWindowState, aImageKey, aWidth, aHeight, aFormat,
aBuffer.mData, aBuffer.mLength);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDeleteImage(const WRImageKey& aImageKey)
{
MOZ_ASSERT(mWRWindowState);
mKeysToDelete.push_back(aImageKey);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvPushDLBuilder()
{
MOZ_ASSERT(mWRState);
wr_push_dl_builder(mWRState);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvPopDLBuilder(const WRRect& aBounds,
const WRRect& aOverflow,
const gfx::Matrix4x4& aMatrix,
const uint64_t& aScrollId)
{
MOZ_ASSERT(mWRState);
wr_pop_dl_builder(mWRWindowState, mWRState, aBounds, aOverflow, &aMatrix.components[0], aScrollId);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPBegin(const uint32_t& aWidth,
const uint32_t& aHeight,
bool* aOutSuccess)
{
MOZ_ASSERT(mWRState);
if (mWidget) {
mozilla::widget::WidgetRenderingContext widgetContext;
#if defined(XP_MACOSX)
widgetContext.mGL = mGLContext;
#endif
if (!mWidget->PreRender(&widgetContext)) {
*aOutSuccess = false;
return IPC_OK();
}
}
mGLContext->MakeCurrent();
wr_dp_begin(mWRWindowState, mWRState, aWidth, aHeight);
*aOutSuccess = true;
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPEnd()
{
MOZ_ASSERT(mWRState);
mGLContext->MakeCurrent();
wr_dp_end(mWRWindowState, mWRState);
mGLContext->SwapBuffers();
if (mWidget) {
mozilla::widget::WidgetRenderingContext widgetContext;
#if defined(XP_MACOSX)
widgetContext.mGL = mGLContext;
#endif
mWidget->PostRender(&widgetContext);
}
DeleteOldImages();
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPPushRect(const WRRect& aBounds,
const WRRect& aClip,
const float& r, const float& g,
const float& b, const float& a)
{
MOZ_ASSERT(mWRState);
wr_dp_push_rect(mWRState, aBounds, aClip, r, g, b, a);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPPushImage(const WRRect& aBounds,
const WRRect& aClip,
const Maybe<WRImageMask>& aMask,
const WRImageKey& aKey)
{
MOZ_ASSERT(mWRState);
wr_dp_push_image(mWRState, aBounds, aClip, aMask.ptrOr(nullptr), aKey);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPPushIframe(const WRRect& aBounds,
const WRRect& aClip,
const uint64_t& aLayersId)
{
MOZ_ASSERT(mWRState);
wr_dp_push_iframe(mWRState, aBounds, aClip, aLayersId);
return IPC_OK();
}
WebRenderBridgeParent::~WebRenderBridgeParent()
{
}
void
WebRenderBridgeParent::DeleteOldImages()
{
for (WRImageKey key : mKeysToDelete) {
wr_delete_image(mWRWindowState, key);
}
mKeysToDelete.clear();
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=4 ts=8 et 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 mozilla_layers_WebRenderBridgeParent_h
#define mozilla_layers_WebRenderBridgeParent_h
#include "GLContextProvider.h"
#include "mozilla/layers/PWebRenderBridgeParent.h"
#include "mozilla/layers/WebRenderTypes.h"
namespace mozilla {
namespace gl {
class GLContext;
}
namespace widget {
class CompositorWidget;
}
namespace layers {
class WebRenderBridgeParent final : public PWebRenderBridgeParent
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeParent)
public:
WebRenderBridgeParent(const uint64_t& aPipelineId,
widget::CompositorWidget* aWidget,
gl::GLContext* aGlContext,
wrwindowstate* aWrWindowState);
uint64_t PipelineId() { return mPipelineId; }
gl::GLContext* GLContext() { return mGLContext.get(); }
wrwindowstate* WindowState() { return mWRWindowState; }
mozilla::ipc::IPCResult RecvCreate(const uint32_t& aWidth,
const uint32_t& aHeight) override;
mozilla::ipc::IPCResult RecvDestroy() override;
mozilla::ipc::IPCResult RecvAddImage(const uint32_t& aWidth,
const uint32_t& aHeight,
const uint32_t& aStride,
const WRImageFormat& aFormat,
const ByteBuffer& aBuffer,
WRImageKey* aOutImageKey) override;
mozilla::ipc::IPCResult RecvUpdateImage(const WRImageKey& aImageKey,
const uint32_t& aWidth,
const uint32_t& aHeight,
const WRImageFormat& aFormat,
const ByteBuffer& aBuffer) override;
mozilla::ipc::IPCResult RecvDeleteImage(const WRImageKey& aImageKey) override;
mozilla::ipc::IPCResult RecvPushDLBuilder() override;
mozilla::ipc::IPCResult RecvPopDLBuilder(const WRRect& aBounds,
const WRRect& aOverflow,
const gfx::Matrix4x4& aMatrix,
const uint64_t& aScrollId) override;
mozilla::ipc::IPCResult RecvDPBegin(const uint32_t& aWidth,
const uint32_t& aHeight,
bool* aOutSuccess) override;
mozilla::ipc::IPCResult RecvDPEnd() override;
mozilla::ipc::IPCResult RecvDPPushRect(const WRRect& aBounds,
const WRRect& aClip,
const float& r,
const float& g,
const float& b,
const float& a) override;
mozilla::ipc::IPCResult RecvDPPushImage(const WRRect& aBounds,
const WRRect& aClip,
const Maybe<WRImageMask>& aMask,
const WRImageKey& aKey) override;
mozilla::ipc::IPCResult RecvDPPushIframe(const WRRect& aBounds,
const WRRect& aClip,
const uint64_t& aLayersId) override;
void ActorDestroy(ActorDestroyReason aWhy) override {}
protected:
virtual ~WebRenderBridgeParent();
void DeleteOldImages();
private:
uint64_t mPipelineId;
RefPtr<widget::CompositorWidget> mWidget;
wrstate* mWRState;
RefPtr<gl::GLContext> mGLContext;
wrwindowstate* mWRWindowState;
std::vector<WRImageKey> mKeysToDelete;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_WebRenderBridgeParent_h

View File

@@ -0,0 +1,123 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "WebRenderCanvasLayer.h"
#include "AsyncCanvasRenderer.h"
#include "gfxUtils.h"
#include "GLContext.h"
#include "GLScreenBuffer.h"
#include "LayersLogging.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "PersistentBufferProvider.h"
#include "SharedSurface.h"
namespace mozilla {
namespace layers {
WebRenderCanvasLayer::~WebRenderCanvasLayer()
{
MOZ_COUNT_DTOR(WebRenderCanvasLayer);
}
void
WebRenderCanvasLayer::RenderLayer()
{
FirePreTransactionCallback();
RefPtr<gfx::SourceSurface> surface;
// Get the canvas buffer
AutoReturnSnapshot autoReturn;
if (mAsyncRenderer) {
MOZ_ASSERT(!mBufferProvider);
MOZ_ASSERT(!mGLContext);
surface = mAsyncRenderer->GetSurface();
} else if (mGLContext) {
gl::SharedSurface* frontbuffer = nullptr;
if (mGLFrontbuffer) {
frontbuffer = mGLFrontbuffer.get();
} else {
gl::GLScreenBuffer* screen = mGLContext->Screen();
const auto& front = screen->Front();
if (front) {
frontbuffer = front->Surf();
}
}
if (!frontbuffer) {
NS_WARNING("Null frame received.");
return;
}
gfx::IntSize readSize(frontbuffer->mSize);
gfx::SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
? gfx::SurfaceFormat::B8G8R8X8
: gfx::SurfaceFormat::B8G8R8A8;
bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
RefPtr<gfx::DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
// There will already be a warning from inside of GetTempSurface, but
// it doesn't hurt to complain:
if (NS_WARN_IF(!resultSurf)) {
return;
}
// Readback handles Flush/MarkDirty.
mGLContext->Readback(frontbuffer, resultSurf);
if (needsPremult) {
gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
}
surface = resultSurf;
} else if (mBufferProvider) {
surface = mBufferProvider->BorrowSnapshot();
autoReturn.mSnapshot = &surface;
autoReturn.mBufferProvider = mBufferProvider;
}
FireDidTransactionCallback();
if (!surface) {
return;
}
WRScrollFrameStackingContextGenerator scrollFrames(this);
RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
gfx::DataSourceSurface::ScopedMap map(dataSurface, gfx::DataSourceSurface::MapType::READ);
//XXX
MOZ_RELEASE_ASSERT(surface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8 ||
surface->GetFormat() == gfx::SurfaceFormat::B8G8R8A8, "bad format");
gfx::IntSize size = surface->GetSize();
WRImageKey key;
gfx::ByteBuffer buf(size.height * map.GetStride(), map.GetData());
WRBridge()->SendAddImage(size.width, size.height, map.GetStride(), RGBA8, buf, &key);
gfx::Matrix4x4 transform;// = GetTransform();
const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
if (needsYFlip) {
transform.PreTranslate(0, size.height, 0).PreScale(1, -1, 1);
}
gfx::Rect rect(0, 0, size.width, size.height);
gfx::Rect clip;
if (GetClipRect().isSome()) {
clip = RelativeToTransformedVisible(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
} else {
clip = rect;
}
if (gfxPrefs::LayersDump()) printf_stderr("CanvasLayer %p using rect:%s clip:%s\n", this, Stringify(rect).c_str(), Stringify(clip).c_str());
WRBridge()->SendPushDLBuilder();
WRBridge()->SendDPPushImage(toWrRect(rect), toWrRect(clip), Nothing(), key);
Manager()->AddImageKeyForDiscard(key);
gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent();
if (gfxPrefs::LayersDump()) printf_stderr("CanvasLayer %p using %s as bounds/overflow, %s for transform\n", this, Stringify(relBounds).c_str(), Stringify(transform).c_str());
WRBridge()->SendPopDLBuilder(toWrRect(relBounds), toWrRect(relBounds), transform, FrameMetrics::NULL_SCROLL_ID);
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERCANVASLAYER_H
#define GFX_WEBRENDERCANVASLAYER_H
#include "CopyableCanvasLayer.h"
#include "WebRenderLayerManager.h"
namespace mozilla {
namespace gfx {
class SourceSurface;
}; // namespace gfx
namespace layers {
class WebRenderCanvasLayer : public WebRenderLayer,
public CopyableCanvasLayer
{
public:
explicit WebRenderCanvasLayer(WebRenderLayerManager* aLayerManager)
: CopyableCanvasLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderCanvasLayer);
}
protected:
virtual ~WebRenderCanvasLayer();
WebRenderLayerManager* Manager()
{
return static_cast<WebRenderLayerManager*>(mManager);
}
public:
Layer* GetLayer() override { return this; }
void RenderLayer() override;
};
} // namespace layers
} // namespace mozilla
#endif // GFX_WEBRENDERCANVASLAYER_H

View File

@@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "WebRenderColorLayer.h"
#include "LayersLogging.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "webrender.h"
namespace mozilla {
namespace layers {
void
WebRenderColorLayer::RenderLayer()
{
WRScrollFrameStackingContextGenerator scrollFrames(this);
gfx::Rect rect = RelativeToParent(GetTransform().TransformBounds(IntRectToRect(mBounds)));
gfx::Rect clip;
if (GetClipRect().isSome()) {
clip = RelativeToParent(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
} else {
clip = rect;
}
if (gfxPrefs::LayersDump()) printf_stderr("ColorLayer %p using rect:%s clip:%s\n", this, Stringify(rect).c_str(), Stringify(clip).c_str());
WRBridge()->SendDPPushRect(toWrRect(rect), toWrRect(clip),
mColor.r, mColor.g, mColor.b, mColor.a);
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERCOLORLAYER_H
#define GFX_WEBRENDERCOLORLAYER_H
#include "Layers.h"
#include "WebRenderLayerManager.h"
namespace mozilla {
namespace layers {
class WebRenderColorLayer : public WebRenderLayer,
public ColorLayer {
public:
explicit WebRenderColorLayer(WebRenderLayerManager* aLayerManager)
: ColorLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderColorLayer);
}
protected:
virtual ~WebRenderColorLayer()
{
MOZ_COUNT_DTOR(WebRenderColorLayer);
}
public:
Layer* GetLayer() override { return this; }
void RenderLayer() override;
};
} // namespace layers
} // namespace mozilla
#endif // GFX_WEBRENDERCOLORLAYER_H

View File

@@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "WebRenderContainerLayer.h"
#include <inttypes.h>
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "LayersLogging.h"
namespace mozilla {
namespace layers {
void
WebRenderContainerLayer::RenderLayer()
{
WRScrollFrameStackingContextGenerator scrollFrames(this);
AutoTArray<Layer*, 12> children;
SortChildrenBy3DZOrder(children);
gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent();
gfx::Matrix4x4 transform;// = GetTransform();
if (gfxPrefs::LayersDump()) printf_stderr("ContainerLayer %p using %s as bounds/overflow, %s as transform\n", this, Stringify(relBounds).c_str(), Stringify(transform).c_str());
WRBridge()->SendPushDLBuilder();
for (Layer* child : children) {
ToWebRenderLayer(child)->RenderLayer();
}
WRBridge()->SendPopDLBuilder(toWrRect(relBounds), toWrRect(relBounds), transform, FrameMetrics::NULL_SCROLL_ID);
}
void
WebRenderRefLayer::RenderLayer()
{
WRScrollFrameStackingContextGenerator scrollFrames(this);
gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent();
gfx::Matrix4x4 transform;// = GetTransform();
if (gfxPrefs::LayersDump()) printf_stderr("RefLayer %p (%" PRIu64 ") using %s as bounds/overflow, %s as transform\n", this, mId, Stringify(relBounds).c_str(), Stringify(transform).c_str());
WRBridge()->SendDPPushIframe(toWrRect(relBounds), toWrRect(relBounds), mId);
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,69 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERCONTAINERLAYER_H
#define GFX_WEBRENDERCONTAINERLAYER_H
#include "Layers.h"
#include "WebRenderLayerManager.h"
namespace mozilla {
namespace layers {
class WebRenderContainerLayer : public WebRenderLayer,
public ContainerLayer
{
public:
explicit WebRenderContainerLayer(WebRenderLayerManager* aManager)
: ContainerLayer(aManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderContainerLayer);
}
protected:
virtual ~WebRenderContainerLayer()
{
MOZ_COUNT_DTOR(WebRenderContainerLayer);
}
public:
Layer* GetLayer() override { return this; }
void RenderLayer() override;
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
{
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
};
class WebRenderRefLayer : public WebRenderLayer,
public RefLayer {
public:
explicit WebRenderRefLayer(WebRenderLayerManager* aManager) :
RefLayer(aManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderRefLayer);
}
protected:
virtual ~WebRenderRefLayer()
{
MOZ_COUNT_DTOR(WebRenderRefLayer);
}
public:
Layer* GetLayer() override { return this; }
void RenderLayer() override;
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
{
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
};
} // namespace layers
} // namespace mozilla
#endif // GFX_WEBRENDERCONTAINERLAYER_H

View File

@@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "WebRenderImageLayer.h"
#include "LayersLogging.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
namespace mozilla {
namespace layers {
using namespace gfx;
already_AddRefed<gfx::SourceSurface>
WebRenderImageLayer::GetAsSourceSurface()
{
AutoLockImage autoLock(mContainer);
Image *image = autoLock.GetImage();
if (!image) {
return nullptr;
}
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
if (!surface || !surface->IsValid()) {
return nullptr;
}
return surface.forget();
}
void
WebRenderImageLayer::RenderLayer()
{
RefPtr<gfx::SourceSurface> surface = GetAsSourceSurface();
if (!surface)
return;
WRScrollFrameStackingContextGenerator scrollFrames(this);
RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::MapType::READ);
//XXX
MOZ_RELEASE_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
surface->GetFormat() == SurfaceFormat::B8G8R8A8, "bad format");
gfx::IntSize size = surface->GetSize();
WRImageKey key;
gfx::ByteBuffer buf(size.height * map.GetStride(), map.GetData());
WRBridge()->SendAddImage(size.width, size.height, map.GetStride(), RGBA8, buf, &key);
Rect rect(0, 0, size.width, size.height);
Rect clip;
if (GetClipRect().isSome()) {
clip = RelativeToTransformedVisible(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
} else {
clip = rect;
}
if (gfxPrefs::LayersDump()) printf_stderr("ImageLayer %p using rect:%s clip:%s\n", this, Stringify(rect).c_str(), Stringify(clip).c_str());
WRBridge()->SendPushDLBuilder();
WRBridge()->SendDPPushImage(toWrRect(rect), toWrRect(clip), Nothing(), key);
Manager()->AddImageKeyForDiscard(key);
Rect relBounds = TransformedVisibleBoundsRelativeToParent();
Matrix4x4 transform;// = GetTransform();
if (gfxPrefs::LayersDump()) printf_stderr("ImageLayer %p using %s as bounds/overflow, %s for transform\n", this, Stringify(relBounds).c_str(), Stringify(transform).c_str());
WRBridge()->SendPopDLBuilder(toWrRect(relBounds), toWrRect(relBounds), transform, FrameMetrics::NULL_SCROLL_ID);
//mContainer->SetImageFactory(originalIF);
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERIMAGELAYER_H
#define GFX_WEBRENDERIMAGELAYER_H
#include "ImageLayers.h"
#include "WebRenderLayerManager.h"
namespace mozilla {
namespace layers {
class WebRenderImageLayer : public WebRenderLayer,
public ImageLayer {
public:
explicit WebRenderImageLayer(WebRenderLayerManager* aLayerManager)
: ImageLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderImageLayer);
}
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
protected:
virtual ~WebRenderImageLayer()
{
MOZ_COUNT_DTOR(WebRenderImageLayer);
}
WebRenderLayerManager* Manager()
{
return static_cast<WebRenderLayerManager*>(mManager);
}
public:
Layer* GetLayer() override { return this; }
void RenderLayer() override;
};
} // namespace layers
} // namespace mozilla
#endif // GFX_WEBRENDERIMAGELAYER_H

View File

@@ -0,0 +1,286 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "WebRenderLayerManager.h"
#include "apz/src/AsyncPanZoomController.h"
#include "LayersLogging.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/AsyncCompositionManager.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#include "nsThreadUtils.h"
#include "TreeTraversal.h"
#include "WebRenderCanvasLayer.h"
#include "WebRenderColorLayer.h"
#include "WebRenderContainerLayer.h"
#include "WebRenderImageLayer.h"
#include "WebRenderPaintedLayer.h"
#include "webrender.h"
namespace mozilla {
using namespace gfx;
namespace layers {
WebRenderLayerManager*
WebRenderLayer::WRManager()
{
return static_cast<WebRenderLayerManager*>(GetLayer()->Manager());
}
WebRenderBridgeChild*
WebRenderLayer::WRBridge()
{
return WRManager()->WRBridge();
}
Rect
WebRenderLayer::RelativeToVisible(Rect aRect)
{
IntRect bounds = GetLayer()->GetVisibleRegion().GetBounds().ToUnknownRect();
aRect.MoveBy(-bounds.x, -bounds.y);
return aRect;
}
Rect
WebRenderLayer::RelativeToTransformedVisible(Rect aRect)
{
IntRect bounds = GetLayer()->GetVisibleRegion().GetBounds().ToUnknownRect();
Rect transformed = GetLayer()->GetTransform().TransformBounds(IntRectToRect(bounds));
aRect.MoveBy(-transformed.x, -transformed.y);
return aRect;
}
Rect
WebRenderLayer::ParentStackingContextBounds(size_t aScrollMetadataIndex)
{
// Walk up to find the parent stacking context. This will be created either
// by the nearest scrollable metrics, or by the parent layer which must be a
// ContainerLayer.
Layer* layer = GetLayer();
for (size_t i = aScrollMetadataIndex + 1; i < layer->GetScrollMetadataCount(); i++) {
if (layer->GetFrameMetrics(i).IsScrollable()) {
return layer->GetFrameMetrics(i).GetCompositionBounds().ToUnknownRect();
}
}
if (layer->GetParent()) {
return IntRectToRect(layer->GetParent()->GetVisibleRegion().GetBounds().ToUnknownRect());
}
return Rect();
}
Rect
WebRenderLayer::RelativeToParent(Rect aRect)
{
Rect parentBounds = ParentStackingContextBounds(-1);
aRect.MoveBy(-parentBounds.x, -parentBounds.y);
return aRect;
}
Rect
WebRenderLayer::TransformedVisibleBoundsRelativeToParent()
{
IntRect bounds = GetLayer()->GetVisibleRegion().GetBounds().ToUnknownRect();
Rect transformed = GetLayer()->GetTransform().TransformBounds(IntRectToRect(bounds));
return RelativeToParent(transformed);
}
WRScrollFrameStackingContextGenerator::WRScrollFrameStackingContextGenerator(
WebRenderLayer* aLayer)
: mLayer(aLayer)
{
Layer* layer = mLayer->GetLayer();
for (size_t i = layer->GetScrollMetadataCount(); i > 0; i--) {
const FrameMetrics& fm = layer->GetFrameMetrics(i - 1);
if (!fm.IsScrollable()) {
continue;
}
if (gfxPrefs::LayersDump()) printf_stderr("Pushing stacking context id %" PRIu64"\n", fm.GetScrollId());
mLayer->WRBridge()->SendPushDLBuilder();
}
}
WRScrollFrameStackingContextGenerator::~WRScrollFrameStackingContextGenerator()
{
Matrix4x4 identity;
Layer* layer = mLayer->GetLayer();
for (size_t i = 0; i < layer->GetScrollMetadataCount(); i++) {
const FrameMetrics& fm = layer->GetFrameMetrics(i);
if (!fm.IsScrollable()) {
continue;
}
Rect bounds = fm.GetCompositionBounds().ToUnknownRect();
Rect overflow = (fm.GetExpandedScrollableRect() * fm.LayersPixelsPerCSSPixel()).ToUnknownRect();
Point scrollPos = (fm.GetScrollOffset() * fm.LayersPixelsPerCSSPixel()).ToUnknownPoint();
Rect parentBounds = mLayer->ParentStackingContextBounds(i);
bounds.MoveBy(-parentBounds.x, -parentBounds.y);
// Subtract the MT scroll position from the overflow here so that the WR
// scroll offset (which is the APZ async scroll component) always fits in
// the available overflow. If we didn't do this and WR did bounds checking
// on the scroll offset, we'd fail those checks.
overflow.MoveBy(bounds.x - scrollPos.x, bounds.y - scrollPos.y);
if (gfxPrefs::LayersDump()) {
printf_stderr("Popping stacking context id %" PRIu64 " with bounds=%s overflow=%s\n",
fm.GetScrollId(), Stringify(bounds).c_str(), Stringify(overflow).c_str());
}
mLayer->WRBridge()->SendPopDLBuilder(toWrRect(bounds), toWrRect(overflow), identity, fm.GetScrollId());
}
}
WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
: mWidget(aWidget)
{
}
void
WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild, uint64_t aLayersId)
{
MOZ_ASSERT(mWRChild == nullptr);
PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId);
MOZ_ASSERT(bridge);
mWRChild = static_cast<WebRenderBridgeChild*>(bridge);
LayoutDeviceIntSize size = mWidget->GetClientSize();
WRBridge()->SendCreate(size.width, size.height);
}
void
WebRenderLayerManager::Destroy()
{
DiscardImages();
}
WebRenderLayerManager::~WebRenderLayerManager()
{
WRBridge()->SendDestroy();
}
CompositorBridgeChild*
WebRenderLayerManager::GetCompositorBridgeChild()
{
return mWidget ? mWidget->GetRemoteRenderer() : nullptr;
}
int32_t
WebRenderLayerManager::GetMaxTextureSize() const
{
return 4096;
}
bool
WebRenderLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
return BeginTransaction();
}
bool
WebRenderLayerManager::BeginTransaction()
{
return true;
}
bool
WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
{
return false;
}
void
WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
DiscardImages();
mPaintedLayerCallback = aCallback;
mPaintedLayerCallbackData = aCallbackData;
if (gfxPrefs::LayersDump()) {
this->Dump();
}
// Since we don't do repeat transactions right now, just set the time
mAnimationReadyTime = TimeStamp::Now();
LayoutDeviceIntSize size = mWidget->GetClientSize();
bool success = false;
WRBridge()->SendDPBegin(size.width, size.height, &success);
if (!success) {
return;
}
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer();
WRBridge()->SendDPEnd();
}
void
WebRenderLayerManager::AddImageKeyForDiscard(WRImageKey key)
{
mImageKeys.push_back(key);
}
void
WebRenderLayerManager::DiscardImages()
{
for (auto key : mImageKeys) {
WRBridge()->SendDeleteImage(key);
}
mImageKeys.clear();
}
void
WebRenderLayerManager::SetRoot(Layer* aLayer)
{
mRoot = aLayer;
}
already_AddRefed<PaintedLayer>
WebRenderLayerManager::CreatePaintedLayer()
{
return MakeAndAddRef<WebRenderPaintedLayer>(this);
}
already_AddRefed<ContainerLayer>
WebRenderLayerManager::CreateContainerLayer()
{
return MakeAndAddRef<WebRenderContainerLayer>(this);
}
already_AddRefed<ImageLayer>
WebRenderLayerManager::CreateImageLayer()
{
return MakeAndAddRef<WebRenderImageLayer>(this);
}
already_AddRefed<CanvasLayer>
WebRenderLayerManager::CreateCanvasLayer()
{
return MakeAndAddRef<WebRenderCanvasLayer>(this);
}
already_AddRefed<ReadbackLayer>
WebRenderLayerManager::CreateReadbackLayer()
{
return nullptr;
}
already_AddRefed<ColorLayer>
WebRenderLayerManager::CreateColorLayer()
{
return MakeAndAddRef<WebRenderColorLayer>(this);
}
already_AddRefed<RefLayer>
WebRenderLayerManager::CreateRefLayer()
{
return MakeAndAddRef<WebRenderRefLayer>(this);
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,141 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERLAYERMANAGER_H
#define GFX_WEBRENDERLAYERMANAGER_H
#include "Layers.h"
#include "mozilla/layers/CompositorController.h"
#include "webrender.h"
class nsIWidget;
namespace mozilla {
namespace layers {
class WebRenderBridgeChild;
template<class T>
static inline WRRect toWrRect(const gfx::RectTyped<T>& rect)
{
WRRect r;
r.x = rect.x;
r.y = rect.y;
r.width = rect.width;
r.height = rect.height;
return r;
}
template<class T>
static inline WRRect toWrRect(const gfx::IntRectTyped<T>& rect)
{
return toWrRect(IntRectToRect(rect));
}
class WebRenderLayerManager;
class APZCTreeManager;
class WebRenderLayer
{
public:
virtual Layer* GetLayer() = 0;
virtual void RenderLayer() = 0;
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; }
static inline WebRenderLayer*
ToWebRenderLayer(Layer* aLayer)
{
return static_cast<WebRenderLayer*>(aLayer->ImplData());
}
WebRenderLayerManager* WRManager();
WebRenderBridgeChild* WRBridge();
gfx::Rect RelativeToVisible(gfx::Rect aRect);
gfx::Rect RelativeToTransformedVisible(gfx::Rect aRect);
gfx::Rect ParentStackingContextBounds(size_t aScrollMetadataIndex);
gfx::Rect RelativeToParent(gfx::Rect aRect);
gfx::Rect TransformedVisibleBoundsRelativeToParent();
};
class MOZ_RAII WRScrollFrameStackingContextGenerator
{
public:
explicit WRScrollFrameStackingContextGenerator(WebRenderLayer* aLayer);
~WRScrollFrameStackingContextGenerator();
private:
WebRenderLayer* mLayer;
};
class WebRenderLayerManager final : public LayerManager
{
public:
explicit WebRenderLayerManager(nsIWidget* aWidget);
void Initialize(PCompositorBridgeChild* aCBChild, uint64_t aLayersId);
virtual void Destroy() override;
protected:
virtual ~WebRenderLayerManager();
public:
WebRenderLayerManager* AsWebRenderLayerManager() override { return this; }
CompositorBridgeChild* GetCompositorBridgeChild();
virtual int32_t GetMaxTextureSize() const override;
virtual bool BeginTransactionWithTarget(gfxContext* aTarget) override;
virtual bool BeginTransaction() override;
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override;
virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags = END_DEFAULT) override;
virtual LayersBackend GetBackendType() override { return LayersBackend::LAYERS_WR; }
virtual void GetBackendName(nsAString& name) override { name.AssignLiteral("WebRender"); }
virtual const char* Name() const override { return "WebRender"; }
virtual void SetRoot(Layer* aLayer) override;
virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() override;
virtual already_AddRefed<ContainerLayer> CreateContainerLayer() override;
virtual already_AddRefed<ImageLayer> CreateImageLayer() override;
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override;
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() override;
virtual already_AddRefed<ColorLayer> CreateColorLayer() override;
virtual already_AddRefed<RefLayer> CreateRefLayer() override;
virtual bool NeedsWidgetInvalidation() override { return true; }
DrawPaintedLayerCallback GetPaintedLayerCallback() const
{ return mPaintedLayerCallback; }
void* GetPaintedLayerCallbackData() const
{ return mPaintedLayerCallbackData; }
// adds an imagekey to a list of keys that will be discarded on the next
// transaction or destruction
void AddImageKeyForDiscard(WRImageKey);
void DiscardImages();
WebRenderBridgeChild* WRBridge() { return mWRChild; }
private:
nsIWidget* MOZ_NON_OWNING_REF mWidget;
std::vector<WRImageKey> mImageKeys;
/* PaintedLayer callbacks; valid at the end of a transaciton,
* while rendering */
DrawPaintedLayerCallback mPaintedLayerCallback;
void *mPaintedLayerCallbackData;
RefPtr<WebRenderBridgeChild> mWRChild;
};
} // namespace layers
} // namespace mozilla
#endif /* GFX_WEBRENDERLAYERMANAGER_H */

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "WebRenderPaintedLayer.h"
#include "LayersLogging.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "gfxUtils.h"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
void
WebRenderPaintedLayer::RenderLayer()
{
LayerIntRegion visibleRegion = GetVisibleRegion();
LayerIntRect bounds = visibleRegion.GetBounds();
LayerIntSize size = bounds.Size();
if (size.IsEmpty()) {
return;
}
WRScrollFrameStackingContextGenerator scrollFrames(this);
WRBridge()->SendPushDLBuilder();
RefPtr<DrawTarget> target = gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, size.ToUnknownSize(), SurfaceFormat::B8G8R8A8);
target->SetTransform(Matrix().PreTranslate(-bounds.x, -bounds.y));
RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
MOZ_ASSERT(ctx); // already checked the target above
Manager()->GetPaintedLayerCallback()(this,
ctx,
visibleRegion.ToUnknownRegion(), visibleRegion.ToUnknownRegion(),
DrawRegionClip::DRAW, nsIntRegion(), Manager()->GetPaintedLayerCallbackData());
#if 0
static int count;
char buf[400];
sprintf(buf, "wrout%d.png", count++);
gfxUtils::WriteAsPNG(target, buf);
#endif
WRImageKey key;
{
unsigned char* data;
IntSize size;
int32_t stride;
SurfaceFormat format;
target->LockBits(&data, &size, &stride, &format);
gfx::ByteBuffer buf(size.height * stride, data);
WRBridge()->SendAddImage(size.width, size.height, stride, RGBA8, buf, &key);
target->ReleaseBits(data);
}
// Since we are creating a stacking context below using the visible region of
// this layer, we need to make sure the image display item has coordinates
// relative to the visible region.
Rect rect = RelativeToVisible(IntRectToRect(bounds.ToUnknownRect()));
Rect clip;
if (GetClipRect().isSome()) {
clip = RelativeToTransformedVisible(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
} else {
clip = rect;
}
if (gfxPrefs::LayersDump()) printf_stderr("PaintedLayer %p using rect:%s clip:%s\n", this, Stringify(rect).c_str(), Stringify(clip).c_str());
WRBridge()->SendDPPushImage(toWrRect(rect), toWrRect(clip), Nothing(), key);
Manager()->AddImageKeyForDiscard(key);
Rect relBounds = TransformedVisibleBoundsRelativeToParent();
Matrix4x4 transform;// = GetTransform();
if (gfxPrefs::LayersDump()) printf_stderr("PaintedLayer %p using %s as bounds/overflow, %s for transform\n", this, Stringify(relBounds).c_str(), Stringify(transform).c_str());
WRBridge()->SendPopDLBuilder(toWrRect(relBounds), toWrRect(relBounds), transform, FrameMetrics::NULL_SCROLL_ID);
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERPAINTEDLAYER_H
#define GFX_WEBRENDERPAINTEDLAYER_H
#include "Layers.h"
#include "WebRenderLayerManager.h"
namespace mozilla {
namespace layers {
class WebRenderPaintedLayer : public WebRenderLayer,
public PaintedLayer {
public:
explicit WebRenderPaintedLayer(WebRenderLayerManager* aLayerManager)
: PaintedLayer(aLayerManager, static_cast<WebRenderLayer*>(this), LayerManager::NONE)
{
MOZ_COUNT_CTOR(WebRenderPaintedLayer);
}
protected:
virtual ~WebRenderPaintedLayer()
{
MOZ_COUNT_DTOR(WebRenderPaintedLayer);
}
WebRenderLayerManager* Manager()
{
return static_cast<WebRenderLayerManager*>(mManager);
}
public:
virtual void InvalidateRegion(const nsIntRegion& aRegion) override
{
mInvalidRegion.Add(aRegion);
mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
}
Layer* GetLayer() override { return this; }
void RenderLayer() override;
};
} // namespace layers
} // namespace mozilla
#endif // GFX_WEBRENDERPAINTEDLAYER_H

View File

@@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_BYTEBUFFER_H
#define GFX_BYTEBUFFER_H
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/Maybe.h"
#include "webrender.h"
typedef mozilla::Maybe<WRImageMask> MaybeImageMask;
namespace mozilla {
namespace gfx {
struct ByteBuffer
{
ByteBuffer(size_t aLength, uint8_t* aData)
: mLength(aLength)
, mData(aData)
, mOwned(false)
{}
ByteBuffer()
: mLength(0)
, mData(nullptr)
, mOwned(false)
{}
bool
Allocate(size_t aLength)
{
MOZ_ASSERT(mData == nullptr);
mData = (uint8_t*)malloc(aLength);
if (!mData) {
return false;
}
mLength = aLength;
mOwned = true;
return true;
}
~ByteBuffer()
{
if (mData && mOwned) {
free(mData);
}
}
size_t mLength;
uint8_t* mData;
bool mOwned;
};
} // namespace gfx
} // namespace mozilla
namespace IPC {
template<>
struct ParamTraits<mozilla::gfx::ByteBuffer>
{
typedef mozilla::gfx::ByteBuffer paramType;
static void
Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mLength);
aMsg->WriteBytes(aParam.mData, aParam.mLength);
}
static bool
Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
size_t length;
return ReadParam(aMsg, aIter, &length)
&& aResult->Allocate(length)
&& aMsg->ReadBytesInto(aIter, aResult->mData, length);
}
};
template<>
struct ParamTraits<WRImageFormat>
: public ContiguousEnumSerializer<
WRImageFormat,
WRImageFormat::Invalid,
WRImageFormat::RGBAF32>
{
};
template<>
struct ParamTraits<WRImageKey>
{
static void
Write(Message* aMsg, const WRImageKey& aParam)
{
WriteParam(aMsg, aParam.a);
WriteParam(aMsg, aParam.b);
}
static bool
Read(const Message* aMsg, PickleIterator* aIter, WRImageKey* aResult)
{
return ReadParam(aMsg, aIter, &aResult->a)
&& ReadParam(aMsg, aIter, &aResult->b);
}
};
template<>
struct ParamTraits<WRRect>
{
static void
Write(Message* aMsg, const WRRect& aParam)
{
WriteParam(aMsg, aParam.x);
WriteParam(aMsg, aParam.y);
WriteParam(aMsg, aParam.width);
WriteParam(aMsg, aParam.height);
}
static bool
Read(const Message* aMsg, PickleIterator* aIter, WRRect* aResult)
{
return ReadParam(aMsg, aIter, &aResult->x)
&& ReadParam(aMsg, aIter, &aResult->y)
&& ReadParam(aMsg, aIter, &aResult->width)
&& ReadParam(aMsg, aIter, &aResult->height);
}
};
template<>
struct ParamTraits<WRImageMask>
{
static void
Write(Message* aMsg, const WRImageMask& aParam)
{
WriteParam(aMsg, aParam.image);
WriteParam(aMsg, aParam.rect);
WriteParam(aMsg, aParam.repeat);
}
static bool
Read(const Message* aMsg, PickleIterator* aIter, WRImageMask* aResult)
{
return ReadParam(aMsg, aIter, &aResult->image)
&& ReadParam(aMsg, aIter, &aResult->rect)
&& ReadParam(aMsg, aIter, &aResult->repeat);
}
};
} // namespace IPC
#endif /* GFX_BYTEBUFFER_H */

View File

@@ -24,6 +24,8 @@ DIRS += [
'config',
]
EXPORTS += ['webrender/webrender.h']
if CONFIG['MOZ_ENABLE_SKIA']:
DIRS += ['skia']

View File

@@ -2432,6 +2432,12 @@ gfxPlatform::AsyncPanZoomEnabled()
if (!BrowserTabsRemoteAutostart()) {
return false;
}
#ifdef MOZ_ENABLE_WEBRENDER
// For webrender hacking we have a special pref to disable APZ even with e10s
if (!gfxPrefs::APZAllowWithWebRender()) {
return false;
}
#endif // MOZ_ENABLE_WEBRENDER
#endif
#ifdef MOZ_WIDGET_ANDROID
return true;

View File

@@ -253,6 +253,7 @@ private:
// The apz prefs are explained in AsyncPanZoomController.cpp
DECL_GFX_PREF(Live, "apz.allow_checkerboarding", APZAllowCheckerboarding, bool, true);
DECL_GFX_PREF(Live, "apz.allow_immediate_handoff", APZAllowImmediateHandoff, bool, true);
DECL_GFX_PREF(Once, "apz.allow_with_webrender", APZAllowWithWebRender, bool, false);
DECL_GFX_PREF(Live, "apz.allow_zooming", APZAllowZooming, bool, false);
DECL_GFX_PREF(Live, "apz.axis_lock.breakout_angle", APZAxisBreakoutAngle, float, float(M_PI / 8.0) /* 22.5 degrees */);
DECL_GFX_PREF(Live, "apz.axis_lock.breakout_threshold", APZAxisBreakoutThreshold, float, 1.0f / 32.0f);

View File

@@ -620,6 +620,7 @@ pref("layout.event-regions.enabled", false);
// gfx/layers/apz/src/AsyncPanZoomController.cpp.
pref("apz.allow_checkerboarding", true);
pref("apz.allow_immediate_handoff", true);
pref("apz.allow_with_webrender", false);
pref("apz.allow_zooming", false);
// Whether to lock touch scrolling to one axis at a time