зеркало из https://github.com/mozilla/gecko-dev.git
Implement vsync notification for remote compositors. (bug 1285625 part 3, r=mchang)
This commit is contained in:
Родитель
0bdcce6956
Коммит
969d03ec34
|
@ -13,11 +13,12 @@ The flow of our rendering engine is as follows:
|
|||
1. Hardware Vsync event occurs on an OS specific *Hardware Vsync Thread* on a per monitor basis.
|
||||
2. The *Hardware Vsync Thread* attached to the monitor notifies the **CompositorVsyncDispatchers** and **RefreshTimerVsyncDispatcher**.
|
||||
3. For every Firefox window on the specific monitor, notify a **CompositorVsyncDispatcher**. The **CompositorVsyncDispatcher** is specific to one window.
|
||||
4. The **CompositorVsyncDispatcher** notifies the **Compositor** that a vsync has occured.
|
||||
5. The **RefreshTimerVsyncDispatcher** notifies the Chrome **RefreshTimer** that a vsync has occured.
|
||||
6. The **RefreshTimerVsyncDispatcher** sends IPC messages to all content processes to tick their respective active **RefreshTimer**.
|
||||
7. The **Compositor** dispatches input events on the *Compositor Thread*, then composites. Input events are only dispatched on the *Compositor Thread* on b2g.
|
||||
8. The **RefreshDriver** paints on the *Main Thread*.
|
||||
4. The **CompositorVsyncDispatcher** notifies a **CompositorWidgetVsyncObserver** when remote compositing, or a **CompositorVsyncScheduler::Observer** when compositing in-process.
|
||||
5. If remote compositing, a vsync notification is sent from the **CompositorWidgetVsyncObserver** to the **VsyncBridgeChild** on the UI process, which sends an IPDL message to the **VsyncBridgeParent** on the compositor thread of the GPU process, which then dispatches to **CompositorVsyncScheduler::Observer**.
|
||||
6. The **RefreshTimerVsyncDispatcher** notifies the Chrome **RefreshTimer** that a vsync has occured.
|
||||
7. The **RefreshTimerVsyncDispatcher** sends IPC messages to all content processes to tick their respective active **RefreshTimer**.
|
||||
8. The **Compositor** dispatches input events on the *Compositor Thread*, then composites. Input events are only dispatched on the *Compositor Thread* on b2g.
|
||||
9. The **RefreshDriver** paints on the *Main Thread*.
|
||||
|
||||
The implementation is broken into the following sections and will reference this figure. Note that **Objects** are bold fonts while *Threads* are italicized.
|
||||
|
||||
|
@ -52,15 +53,29 @@ On OS X, this is through **CVDisplayLinkRef**.
|
|||
On Windows, it should be through **DwmGetCompositionTimingInfo**.
|
||||
|
||||
#Compositor
|
||||
When the **CompositorVsyncDispatcher** is notified of the vsync event, the **CompositorVsyncObserver** associated with the **CompositorVsyncDispatcher** begins execution.
|
||||
Since the **CompositorVsyncDispatcher** executes on the *Hardware Vsync Thread* and the **Compositor** composites on the *CompositorThread*, the **CompositorVsyncObserver** posts a task to the *CompositorThread*.
|
||||
When the **CompositorVsyncDispatcher** is notified of the vsync event, the **CompositorVsyncScheduler::Observer** associated with the **CompositorVsyncDispatcher** begins execution.
|
||||
Since the **CompositorVsyncDispatcher** executes on the *Hardware Vsync Thread* and the **Compositor** composites on the *CompositorThread*, the **CompositorVsyncScheduler::Observer** posts a task to the *CompositorThread*.
|
||||
The **CompositorBridgeParent** then composites.
|
||||
The model where the **CompositorVsyncDispatcher** notifies components on the *Hardware Vsync Thread*, and the component schedules the task on the appropriate thread is used everywhere.
|
||||
|
||||
The **CompositorVsyncObserver** listens to vsync events as needed and stops listening to vsync when composites are no longer scheduled or required.
|
||||
Every **CompositorBridgeParent** is associated and tied to one **CompositorVsyncObserver**, which is associated with the **CompositorVsyncDispatcher**.
|
||||
The **CompositorVsyncScheduler::Observer** listens to vsync events as needed and stops listening to vsync when composites are no longer scheduled or required.
|
||||
Every **CompositorBridgeParent** is associated and tied to one **CompositorVsyncScheduler::Observer**, which is associated with the **CompositorVsyncDispatcher**.
|
||||
Each **CompositorBridgeParent** is associated with one widget and is created when a new platform window or **nsBaseWidget** is created.
|
||||
The **CompositorBridgeParent**, **CompositorVsyncDispatcher**, **CompositorVsyncObserver**, and **nsBaseWidget** all have the same lifetimes, which are created and destroyed together.
|
||||
The **CompositorBridgeParent**, **CompositorVsyncDispatcher**, **CompositorVsyncScheduler::Observer**, and **nsBaseWidget** all have the same lifetimes, which are created and destroyed together.
|
||||
|
||||
##Out-of-process Compositors
|
||||
When compositing out-of-process, this model changes slightly.
|
||||
In this case there are effectively two observers: a UI process observer (**CompositorWidgetVsyncObserver**), and the **CompositorVsyncScheduler::Observer** in the GPU process.
|
||||
There are also two dispatchers: the widget dispatcher in the UI process (**CompositorVsyncDispatcher**), and the IPDL-based dispatcher in the GPU process (**CompositorBridgeParent::NotifyVsync**).
|
||||
The UI process observer and the GPU process dispatcher are linked via an IPDL protocol called PVsyncBridge.
|
||||
**PVsyncBridge** is a top-level protocol for sending vsync notifications to the compositor thread in the GPU process.
|
||||
The compositor controls vsync observation through a separate actor, **PCompositorWidget**, which (as a subactor for **CompositorBridgeChild**) links the compositor thread in the GPU process to the main thread in the UI process.
|
||||
|
||||
Out-of-process compositors do not go through **CompositorVsyncDispatcher** directly.
|
||||
Instead, the **CompositorWidgetDelegate** in the UI process creates one, and gives it a **CompositorWidgetVsyncObserver**.
|
||||
This observer forwards notifications to a Vsync I/O thread, where **VsyncBridgeChild** then forwards the notification again to the compositor thread in the GPU process.
|
||||
The notification is received by a **VsyncBridgeParent**.
|
||||
The GPU process uses the layers ID in the notification to find the correct compositor to dispatch the notification to.
|
||||
|
||||
###CompositorVsyncDispatcher
|
||||
The **CompositorVsyncDispatcher** executes on the *Hardware Vsync Thread*.
|
||||
|
@ -69,6 +84,10 @@ The **CompositorVsyncDispatcher** is responsible for notifying the **CompositorB
|
|||
There can be multiple **CompositorVsyncDispatchers** per **Display**, one **CompositorVsyncDispatcher** per window.
|
||||
The only responsibility of the **CompositorVsyncDispatcher** is to notify components when a vsync event has occured, and to stop listening to vsync when no components require vsync events.
|
||||
We require one **CompositorVsyncDispatcher** per window so that we can handle multiple **Displays**.
|
||||
When compositing in-process, the **CompositorVsyncDispatcher** is attached to the CompositorWidget for the
|
||||
window. When out-of-process, it is attached to the CompositorWidgetDelegate, which forwards
|
||||
observer notifications over IPDL. In the latter case, its lifetime is tied to a CompositorSession
|
||||
rather than the nsIWidget.
|
||||
|
||||
###Multiple Displays
|
||||
The **VsyncSource** has an API to switch a **CompositorVsyncDispatcher** from one **Display** to another **Display**.
|
||||
|
@ -80,14 +99,14 @@ The **CompositorVsyncDispatcher** then notifies the **VsyncSource** to switch to
|
|||
Because the notification works through the **nsIWidget**, the actual switching of the **CompositorVsyncDispatcher** to the correct **Display** should occur on the *Main Thread*.
|
||||
The current implementation of Silk does not handle this case and needs to be built out.
|
||||
|
||||
###CompositorVsyncObserver
|
||||
The **CompositorVsyncObserver** handles the vsync notifications and interactions with the **CompositorVsyncDispatcher**.
|
||||
When the **Compositor** requires a scheduled composite, it notifies the **CompositorVsyncObserver** that it needs to listen to vsync.
|
||||
The **CompositorVsyncObserver** then observes / unobserves vsync as needed from the **CompositorVsyncDispatcher** to enable composites.
|
||||
###CompositorVsyncScheduler::Observer
|
||||
The **CompositorVsyncScheduler::Observer** handles the vsync notifications and interactions with the **CompositorVsyncDispatcher**.
|
||||
When the **Compositor** requires a scheduled composite, it notifies the **CompositorVsyncScheduler::Observer** that it needs to listen to vsync.
|
||||
The **CompositorVsyncScheduler::Observer** then observes / unobserves vsync as needed from the **CompositorVsyncDispatcher** to enable composites.
|
||||
|
||||
###GeckoTouchDispatcher
|
||||
The **GeckoTouchDispatcher** is a singleton that resamples touch events to smooth out jank while tracking a user's finger.
|
||||
Because input and composite are linked together, the **CompositorVsyncObserver** has a reference to the **GeckoTouchDispatcher** and vice versa.
|
||||
Because input and composite are linked together, the **CompositorVsyncScheduler::Observer** has a reference to the **GeckoTouchDispatcher** and vice versa.
|
||||
|
||||
###Input Events
|
||||
One large goal of Silk is to align touch events with vsync events.
|
||||
|
@ -115,25 +134,25 @@ When the [nsBaseWidget shuts down](http://hg.mozilla.org/mozilla-central/file/0d
|
|||
During nsBaseWidget::DestroyCompositor, it first destroys the CompositorBridgeChild.
|
||||
CompositorBridgeChild sends a sync IPC call to CompositorBridgeParent::RecvStop, which calls [CompositorBridgeParent::Destroy](http://hg.mozilla.org/mozilla-central/file/ab0490972e1e/gfx/layers/ipc/CompositorBridgeParent.cpp#l509).
|
||||
During this time, the *main thread* is blocked on the parent process.
|
||||
CompositorBridgeParent::RecvStop runs on the *Compositor thread* and cleans up some resources, including setting the **CompositorVsyncObserver** to nullptr.
|
||||
CompositorBridgeParent::RecvStop runs on the *Compositor thread* and cleans up some resources, including setting the **CompositorVsyncScheduler::Observer** to nullptr.
|
||||
CompositorBridgeParent::RecvStop also explicitly keeps the CompositorBridgeParent alive and posts another task to run CompositorBridgeParent::DeferredDestroy on the Compositor loop so that all ipdl code can finish executing.
|
||||
The **CompositorVsyncObserver** also unobserves from vsync and cancels any pending composite tasks.
|
||||
The **CompositorVsyncScheduler::Observer** also unobserves from vsync and cancels any pending composite tasks.
|
||||
Once CompositorBridgeParent::RecvStop finishes, the *main thread* in the parent process continues shutting down the nsBaseWidget.
|
||||
|
||||
At the same time, the *Compositor thread* is executing tasks until CompositorBridgeParent::DeferredDestroy runs, which flushes the compositor message loop.
|
||||
Now we have two tasks as both the nsBaseWidget releases a reference to the Compositor on the *main thread* during destruction and the CompositorBridgeParent::DeferredDestroy releases a reference to the CompositorBridgeParent on the *Compositor Thread*.
|
||||
Finally, the CompositorBridgeParent itself is destroyed on the *main thread* once both references are gone due to explicit [main thread destruction](http://hg.mozilla.org/mozilla-central/file/50b95032152c/gfx/layers/ipc/CompositorBridgeParent.h#l148).
|
||||
|
||||
With the **CompositorVsyncObserver**, any accesses to the widget after nsBaseWidget::DestroyCompositor executes are invalid.
|
||||
Any accesses to the compositor between the time the nsBaseWidget::DestroyCompositor runs and the CompositorVsyncObserver's destructor runs aren't safe yet a hardware vsync event could occur between these times.
|
||||
With the **CompositorVsyncScheduler::Observer**, any accesses to the widget after nsBaseWidget::DestroyCompositor executes are invalid.
|
||||
Any accesses to the compositor between the time the nsBaseWidget::DestroyCompositor runs and the CompositorVsyncScheduler::Observer's destructor runs aren't safe yet a hardware vsync event could occur between these times.
|
||||
Since any tasks posted on the Compositor loop after CompositorBridgeParent::DeferredDestroy is posted are invalid, we make sure that no vsync tasks can be posted once CompositorBridgeParent::RecvStop executes and DeferredDestroy is posted on the Compositor thread.
|
||||
When the sync call to CompositorBridgeParent::RecvStop executes, we explicitly set the CompositorVsyncObserver to null to prevent vsync notifications from occurring.
|
||||
If vsync notifications were allowed to occur, since the **CompositorVsyncObserver**'s vsync notification executes on the *hardware vsync thread*, it would post a task to the Compositor loop and may execute after CompositorBridgeParent::DeferredDestroy.
|
||||
Thus, we explicitly shut down vsync events in the **CompositorVsyncDispatcher** and **CompositorVsyncObserver** during nsBaseWidget::Shutdown to prevent any vsync tasks from executing after CompositorBridgeParent::DeferredDestroy.
|
||||
When the sync call to CompositorBridgeParent::RecvStop executes, we explicitly set the CompositorVsyncScheduler::Observer to null to prevent vsync notifications from occurring.
|
||||
If vsync notifications were allowed to occur, since the **CompositorVsyncScheduler::Observer**'s vsync notification executes on the *hardware vsync thread*, it would post a task to the Compositor loop and may execute after CompositorBridgeParent::DeferredDestroy.
|
||||
Thus, we explicitly shut down vsync events in the **CompositorVsyncDispatcher** and **CompositorVsyncScheduler::Observer** during nsBaseWidget::Shutdown to prevent any vsync tasks from executing after CompositorBridgeParent::DeferredDestroy.
|
||||
|
||||
The **CompositorVsyncDispatcher** may be destroyed on either the *main thread* or *Compositor Thread*, since both the nsBaseWidget and **CompositorVsyncObserver** race to destroy on different threads.
|
||||
The **CompositorVsyncDispatcher** may be destroyed on either the *main thread* or *Compositor Thread*, since both the nsBaseWidget and **CompositorVsyncScheduler::Observer** race to destroy on different threads.
|
||||
nsBaseWidget is destroyed on the *main thread* and releases a reference to the **CompositorVsyncDispatcher** during destruction.
|
||||
The **CompositorVsyncObserver** has a race to be destroyed either during CompositorBridgeParent shutdown or from the **GeckoTouchDispatcher** which is destroyed on the main thread with [ClearOnShutdown](http://hg.mozilla.org/mozilla-central/file/21567e9a6e40/xpcom/base/ClearOnShutdown.h#l15).
|
||||
The **CompositorVsyncScheduler::Observer** has a race to be destroyed either during CompositorBridgeParent shutdown or from the **GeckoTouchDispatcher** which is destroyed on the main thread with [ClearOnShutdown](http://hg.mozilla.org/mozilla-central/file/21567e9a6e40/xpcom/base/ClearOnShutdown.h#l15).
|
||||
Whichever object, the CompositorBridgeParent or the **GeckoTouchDispatcher** is destroyed last will hold the last reference to the **CompositorVsyncDispatcher**, which destroys the object.
|
||||
|
||||
#Refresh Driver
|
||||
|
@ -212,14 +231,14 @@ There is still only one **VsyncParent/VsyncChild** pair, just each vsync notific
|
|||
|
||||
#Object Lifetime
|
||||
1. CompositorVsyncDispatcher - Lives as long as the nsBaseWidget associated with the VsyncDispatcher
|
||||
2. CompositorVsyncObserver - Lives and dies the same time as the CompositorBridgeParent.
|
||||
2. CompositorVsyncScheduler::Observer - Lives and dies the same time as the CompositorBridgeParent.
|
||||
3. RefreshTimerVsyncDispatcher - As long as the associated display object, which is the lifetime of Firefox.
|
||||
4. VsyncSource - Lives as long as the gfxPlatform on the chrome process, which is the lifetime of Firefox.
|
||||
5. VsyncParent/VsyncChild - Lives as long as the content process
|
||||
6. RefreshTimer - Lives as long as the process
|
||||
|
||||
#Threads
|
||||
All **VsyncObservers** are notified on the *Hardware Vsync Thread*. It is the responsibility of the **VsyncObservers** to post tasks to their respective correct thread. For example, the **CompositorVsyncObserver** will be notified on the *Hardware Vsync Thread*, and post a task to the *Compositor Thread* to do the actual composition.
|
||||
All **VsyncObservers** are notified on the *Hardware Vsync Thread*. It is the responsibility of the **VsyncObservers** to post tasks to their respective correct thread. For example, the **CompositorVsyncScheduler::Observer** will be notified on the *Hardware Vsync Thread*, and post a task to the *Compositor Thread* to do the actual composition.
|
||||
|
||||
1. Compositor Thread - Nothing changes
|
||||
2. Main Thread - PVsyncChild receives IPC messages on the main thread. We also enable/disable vsync on the main thread.
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
|
||||
/* 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 "CompositorWidgetVsyncObserver.h"
|
||||
#include "mozilla/gfx/VsyncBridgeChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
CompositorWidgetVsyncObserver::CompositorWidgetVsyncObserver(
|
||||
RefPtr<VsyncBridgeChild> aVsyncBridge,
|
||||
const uint64_t& aRootLayerTreeId)
|
||||
: mVsyncBridge(aVsyncBridge),
|
||||
mRootLayerTreeId(aRootLayerTreeId)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorWidgetVsyncObserver::NotifyVsync(TimeStamp aTimeStamp)
|
||||
{
|
||||
// Vsync notifications should only arrive on the vsync thread.
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
mVsyncBridge->NotifyVsync(aTimeStamp, mRootLayerTreeId);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
|
||||
/* 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_gfx_ipc_CompositorWidgetVsyncObserver_h
|
||||
#define mozilla_gfx_ipc_CompositorWidgetVsyncObserver_h
|
||||
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class VsyncBridgeChild;
|
||||
} // namespace gfx
|
||||
|
||||
namespace widget {
|
||||
|
||||
class CompositorWidgetVsyncObserver : public VsyncObserver
|
||||
{
|
||||
typedef gfx::VsyncBridgeChild VsyncBridgeChild;
|
||||
|
||||
public:
|
||||
CompositorWidgetVsyncObserver(RefPtr<VsyncBridgeChild> aVsyncBridge,
|
||||
const uint64_t& aRootLayerTreeId);
|
||||
|
||||
bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
|
||||
|
||||
private:
|
||||
RefPtr<VsyncBridgeChild> mVsyncBridge;
|
||||
uint64_t mRootLayerTreeId;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_gfx_ipc_CompositorWidgetVsyncObserver_h
|
|
@ -13,6 +13,7 @@
|
|||
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
|
||||
# include "mozilla/widget/CompositorWidgetChild.h"
|
||||
#endif
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "VsyncBridgeChild.h"
|
||||
#include "VsyncIOThreadHolder.h"
|
||||
|
@ -217,7 +218,7 @@ GPUProcessManager::DestroyProcess()
|
|||
}
|
||||
|
||||
RefPtr<CompositorSession>
|
||||
GPUProcessManager::CreateTopLevelCompositor(nsIWidget* aWidget,
|
||||
GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
|
||||
ClientLayerManager* aLayerManager,
|
||||
CSSToLayoutDeviceScale aScale,
|
||||
bool aUseAPZ,
|
||||
|
@ -254,7 +255,7 @@ GPUProcessManager::CreateTopLevelCompositor(nsIWidget* aWidget,
|
|||
}
|
||||
|
||||
RefPtr<CompositorSession>
|
||||
GPUProcessManager::CreateRemoteSession(nsIWidget* aWidget,
|
||||
GPUProcessManager::CreateRemoteSession(nsBaseWidget* aWidget,
|
||||
ClientLayerManager* aLayerManager,
|
||||
const uint64_t& aRootLayerTreeId,
|
||||
CSSToLayoutDeviceScale aScale,
|
||||
|
@ -296,7 +297,11 @@ GPUProcessManager::CreateRemoteSession(nsIWidget* aWidget,
|
|||
if (!ok)
|
||||
return nullptr;
|
||||
|
||||
CompositorWidgetChild* widget = new CompositorWidgetChild(aWidget);
|
||||
RefPtr<CompositorVsyncDispatcher> dispatcher = aWidget->GetCompositorVsyncDispatcher();
|
||||
RefPtr<CompositorWidgetVsyncObserver> observer =
|
||||
new CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
|
||||
|
||||
CompositorWidgetChild* widget = new CompositorWidgetChild(dispatcher, observer);
|
||||
if (!child->SendPCompositorWidgetConstructor(widget, initData))
|
||||
return nullptr;
|
||||
if (!child->SendInitialize(aRootLayerTreeId))
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "mozilla/ipc/TaskFactory.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
class nsBaseWidget;
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -71,7 +73,7 @@ public:
|
|||
void EnsureGPUReady();
|
||||
|
||||
RefPtr<CompositorSession> CreateTopLevelCompositor(
|
||||
nsIWidget* aWidget,
|
||||
nsBaseWidget* aWidget,
|
||||
ClientLayerManager* aLayerManager,
|
||||
CSSToLayoutDeviceScale aScale,
|
||||
bool aUseAPZ,
|
||||
|
@ -142,7 +144,7 @@ private:
|
|||
void ShutdownVsyncIOThread();
|
||||
|
||||
RefPtr<CompositorSession> CreateRemoteSession(
|
||||
nsIWidget* aWidget,
|
||||
nsBaseWidget* aWidget,
|
||||
ClientLayerManager* aLayerManager,
|
||||
const uint64_t& aRootLayerTreeId,
|
||||
CSSToLayoutDeviceScale aScale,
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace gfx {
|
|||
sync protocol PVsyncBridge
|
||||
{
|
||||
parent:
|
||||
async NotifyVsync(TimeStamp vsyncTimeStamp);
|
||||
async NotifyVsync(TimeStamp vsyncTimeStamp, uint64_t layersId);
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -51,10 +51,60 @@ VsyncBridgeChild::Open(Endpoint<PVsyncBridgeChild>&& aEndpoint)
|
|||
AddRef();
|
||||
}
|
||||
|
||||
class NotifyVsyncTask : public Runnable
|
||||
{
|
||||
public:
|
||||
NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge,
|
||||
TimeStamp aTimeStamp,
|
||||
const uint64_t& aLayersId)
|
||||
: mVsyncBridge(aVsyncBridge),
|
||||
mTimeStamp(aTimeStamp),
|
||||
mLayersId(aLayersId)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mVsyncBridge->NotifyVsyncImpl(mTimeStamp, mLayersId);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<VsyncBridgeChild> mVsyncBridge;
|
||||
TimeStamp mTimeStamp;
|
||||
uint64_t mLayersId;
|
||||
};
|
||||
|
||||
bool
|
||||
VsyncBridgeChild::IsOnVsyncIOThread() const
|
||||
{
|
||||
return MessageLoop::current() == mLoop;
|
||||
}
|
||||
|
||||
void
|
||||
VsyncBridgeChild::NotifyVsync(TimeStamp aTimeStamp, const uint64_t& aLayersId)
|
||||
{
|
||||
// This should be on the Vsync thread (not the Vsync I/O thread).
|
||||
MOZ_ASSERT(!IsOnVsyncIOThread());
|
||||
|
||||
RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aTimeStamp, aLayersId);
|
||||
mLoop->PostTask(task.forget());
|
||||
}
|
||||
|
||||
void
|
||||
VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp, const uint64_t& aLayersId)
|
||||
{
|
||||
// This should be on the Vsync I/O thread.
|
||||
MOZ_ASSERT(IsOnVsyncIOThread());
|
||||
|
||||
if (!mProcessToken) {
|
||||
return;
|
||||
}
|
||||
SendNotifyVsync(aTimeStamp, aLayersId);
|
||||
}
|
||||
|
||||
void
|
||||
VsyncBridgeChild::Close()
|
||||
{
|
||||
if (MessageLoop::current() != mLoop) {
|
||||
if (!IsOnVsyncIOThread()) {
|
||||
mLoop->PostTask(NewRunnableMethod(this, &VsyncBridgeChild::Close));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ class VsyncIOThreadHolder;
|
|||
|
||||
class VsyncBridgeChild final : public PVsyncBridgeChild
|
||||
{
|
||||
friend class NotifyVsyncTask;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncBridgeChild)
|
||||
|
||||
|
@ -29,12 +31,18 @@ public:
|
|||
void DeallocPVsyncBridgeChild() override;
|
||||
void ProcessingError(Result aCode, const char* aReason) override;
|
||||
|
||||
void NotifyVsync(TimeStamp aTimeStamp, const uint64_t& aLayersId);
|
||||
|
||||
private:
|
||||
VsyncBridgeChild(RefPtr<VsyncIOThreadHolder>, const uint64_t& aProcessToken);
|
||||
~VsyncBridgeChild();
|
||||
|
||||
void Open(Endpoint<PVsyncBridgeChild>&& aEndpoint);
|
||||
|
||||
void NotifyVsyncImpl(TimeStamp aTimeStamp, const uint64_t& aLayersId);
|
||||
|
||||
bool IsOnVsyncIOThread() const;
|
||||
|
||||
private:
|
||||
RefPtr<VsyncIOThreadHolder> mThread;
|
||||
MessageLoop* mLoop;
|
||||
|
|
|
@ -44,8 +44,9 @@ VsyncBridgeParent::Open(Endpoint<PVsyncBridgeParent>&& aEndpoint)
|
|||
}
|
||||
|
||||
bool
|
||||
VsyncBridgeParent::RecvNotifyVsync(const TimeStamp& vsyncTimeStamp)
|
||||
VsyncBridgeParent::RecvNotifyVsync(const TimeStamp& aTimeStamp, const uint64_t& aLayersId)
|
||||
{
|
||||
CompositorBridgeParent::NotifyVsync(aTimeStamp, aLayersId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
|
||||
static RefPtr<VsyncBridgeParent> Start(Endpoint<PVsyncBridgeParent>&& aEndpoint);
|
||||
|
||||
bool RecvNotifyVsync(const TimeStamp& vsyncTimeStamp) override;
|
||||
bool RecvNotifyVsync(const TimeStamp& vsyncTimeStamp, const uint64_t& aLayersId) override;
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
void DeallocPVsyncBridgeParent() override;
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@ EXPORTS.mozilla.layers += [
|
|||
'RemoteCompositorSession.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.widget += [
|
||||
'CompositorWidgetVsyncObserver.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
EXPORTS.mozilla.gfx += [
|
||||
'SharedDIBSurface.h',
|
||||
|
@ -39,6 +43,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'CompositorSession.cpp',
|
||||
'CompositorWidgetVsyncObserver.cpp',
|
||||
'D3DMessageUtils.cpp',
|
||||
'GPUChild.cpp',
|
||||
'GPUParent.cpp',
|
||||
|
|
|
@ -269,7 +269,7 @@ CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorBridgeParent* aComp
|
|||
#endif
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread() || XRE_GetProcessType() == GeckoProcessType_GPU);
|
||||
mVsyncObserver = new Observer(this);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
GeckoTouchDispatcher::GetInstance()->SetCompositorVsyncScheduler(this);
|
||||
|
@ -451,8 +451,10 @@ CompositorVsyncScheduler::SetNeedsComposite()
|
|||
bool
|
||||
CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
// Called from the vsync dispatch thread
|
||||
MOZ_ASSERT(!CompositorThreadHolder::IsInCompositorThread());
|
||||
// Called from the vsync dispatch thread. When in the GPU Process, that's
|
||||
// the same as the compositor thread.
|
||||
MOZ_ASSERT_IF(XRE_IsParentProcess(), !CompositorThreadHolder::IsInCompositorThread());
|
||||
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU, CompositorThreadHolder::IsInCompositorThread());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
PostCompositeTask(aVsyncTimestamp);
|
||||
return true;
|
||||
|
@ -639,7 +641,6 @@ CompositorBridgeParent::InitSameProcess(widget::CompositorWidget* aWidget,
|
|||
if (aUseAPZ) {
|
||||
mApzcTreeManager = new APZCTreeManager();
|
||||
}
|
||||
mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
|
||||
|
||||
// IPDL initialization. mSelfRef is cleared in DeferredDestroy.
|
||||
SetOtherProcessId(base::GetCurrentProcId());
|
||||
|
@ -690,6 +691,8 @@ CompositorBridgeParent::Initialize()
|
|||
}
|
||||
|
||||
LayerScope::SetPixelScale(mScale.scale);
|
||||
|
||||
mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
@ -1687,6 +1690,28 @@ CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id)
|
|||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp, const uint64_t& aLayersId)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
auto it = sIndirectLayerTrees.find(aLayersId);
|
||||
if (it == sIndirectLayerTrees.end())
|
||||
return;
|
||||
|
||||
CompositorBridgeParent* cbp = it->second.mParent;
|
||||
if (!cbp || !cbp->mWidget)
|
||||
return;
|
||||
|
||||
RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
|
||||
if (!obs)
|
||||
return;
|
||||
|
||||
obs->NotifyVsync(aTimeStamp);
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorBridgeParent::RecvNotifyChildCreated(const uint64_t& child)
|
||||
{
|
||||
|
|
|
@ -401,6 +401,11 @@ public:
|
|||
*/
|
||||
static CompositorBridgeParent* GetCompositorBridgeParent(uint64_t id);
|
||||
|
||||
/**
|
||||
* Notify the compositor for the given layer tree that vsync has occurred.
|
||||
*/
|
||||
static void NotifyVsync(const TimeStamp& aTimeStamp, const uint64_t& aLayersId);
|
||||
|
||||
/**
|
||||
* Set aController as the pan/zoom callback for the subtree referred
|
||||
* to by aLayersId.
|
||||
|
|
|
@ -125,8 +125,6 @@ TEST_F(VsyncTester, EnableVsync)
|
|||
// Test that if we have vsync enabled, the display should get vsync notifications
|
||||
TEST_F(VsyncTester, CompositorGetVsyncNotifications)
|
||||
{
|
||||
CompositorVsyncDispatcher::SetThreadAssertionsEnabled(false);
|
||||
|
||||
VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
|
||||
globalDisplay.DisableVsync();
|
||||
ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
|
||||
|
|
|
@ -70,5 +70,15 @@ CompositorWidget::GetGLFrameBufferFormat()
|
|||
return LOCAL_GL_RGBA;
|
||||
}
|
||||
|
||||
RefPtr<VsyncObserver>
|
||||
CompositorWidget::GetVsyncObserver() const
|
||||
{
|
||||
// This should only used when the widget is in the GPU process, and should be
|
||||
// implemented by IPDL-enabled CompositorWidgets.
|
||||
// GPU process does not have a CompositorVsyncDispatcher.
|
||||
MOZ_ASSERT_UNREACHABLE("Must be implemented by derived class");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -223,10 +223,15 @@ public:
|
|||
virtual already_AddRefed<gfx::SourceSurface> EndBackBufferDrawing();
|
||||
|
||||
/**
|
||||
* Observer or unobserve vsync.
|
||||
* Observe or unobserve vsync.
|
||||
*/
|
||||
virtual void ObserveVsync(VsyncObserver* aObserver) = 0;
|
||||
|
||||
/**
|
||||
* This is only used by out-of-process compositors.
|
||||
*/
|
||||
virtual RefPtr<VsyncObserver> GetVsyncObserver() const;
|
||||
|
||||
virtual WinCompositorWidget* AsWindows() {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ sync protocol PCompositorWidget
|
|||
|
||||
parent:
|
||||
async __delete__();
|
||||
|
||||
child:
|
||||
async ObserveVsync();
|
||||
async UnobserveVsync();
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "gfxPlatform.h"
|
||||
#include "mozilla/layers/Compositor.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
#include "GeckoProfiler.h"
|
||||
|
@ -16,14 +17,6 @@
|
|||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
static bool sThreadAssertionsEnabled = true;
|
||||
|
||||
void CompositorVsyncDispatcher::SetThreadAssertionsEnabled(bool aEnable)
|
||||
{
|
||||
// Should only be used in test environments
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sThreadAssertionsEnabled = aEnable;
|
||||
}
|
||||
|
||||
CompositorVsyncDispatcher::CompositorVsyncDispatcher()
|
||||
: mCompositorObserverLock("CompositorObserverLock")
|
||||
|
@ -53,16 +46,6 @@ CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositorVsyncDispatcher::AssertOnCompositorThread()
|
||||
{
|
||||
if (!sThreadAssertionsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
Compositor::AssertOnCompositorThread();
|
||||
}
|
||||
|
||||
void
|
||||
CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
|
||||
{
|
||||
|
@ -82,7 +65,11 @@ CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
|
|||
void
|
||||
CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
|
||||
{
|
||||
AssertOnCompositorThread();
|
||||
// When remote compositing or running gtests, vsync observation is
|
||||
// initiated on the main thread. Otherwise, it is initiated from the compositor
|
||||
// thread.
|
||||
MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
|
||||
|
||||
{ // scope lock
|
||||
MutexAutoLock lock(mCompositorObserverLock);
|
||||
mCompositorVsyncObserver = aVsyncObserver;
|
||||
|
|
|
@ -31,7 +31,18 @@ protected:
|
|||
virtual ~VsyncObserver() {}
|
||||
}; // VsyncObserver
|
||||
|
||||
// Used to dispatch vsync events in the parent process to compositors
|
||||
// Used to dispatch vsync events in the parent process to compositors.
|
||||
//
|
||||
// When the compositor is in-process, CompositorWidgets own a
|
||||
// CompositorVsyncDispatcher, and directly attach the compositor's observer
|
||||
// to it.
|
||||
//
|
||||
// When the compositor is out-of-process, the CompositorWidgetDelegate owns
|
||||
// the vsync dispatcher instead. The widget receives vsync observer/unobserve
|
||||
// commands via IPDL, and uses this to attach a CompositorWidgetVsyncObserver.
|
||||
// This observer forwards vsync notifications (on the vsync thread) to a
|
||||
// dedicated vsync I/O thread, which then forwards the notification to the
|
||||
// compositor thread in the compositor process.
|
||||
class CompositorVsyncDispatcher final
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncDispatcher)
|
||||
|
@ -46,13 +57,7 @@ public:
|
|||
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
|
||||
void Shutdown();
|
||||
|
||||
// This can be used to enable or disable thread assertions.
|
||||
// This is useful for gtests because usually things run
|
||||
// in only one thread in that environment
|
||||
static void SetThreadAssertionsEnabled(bool aEnable);
|
||||
|
||||
private:
|
||||
void AssertOnCompositorThread();
|
||||
virtual ~CompositorVsyncDispatcher();
|
||||
void ObserveVsync(bool aEnable);
|
||||
|
||||
|
|
|
@ -5,12 +5,19 @@
|
|||
|
||||
#include "CompositorWidgetChild.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/widget/CompositorWidgetVsyncObserver.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "VsyncDispatcher.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
CompositorWidgetChild::CompositorWidgetChild(nsIWidget* aWidget)
|
||||
CompositorWidgetChild::CompositorWidgetChild(RefPtr<CompositorVsyncDispatcher> aVsyncDispatcher,
|
||||
RefPtr<CompositorWidgetVsyncObserver> aVsyncObserver)
|
||||
: mVsyncDispatcher(aVsyncDispatcher),
|
||||
mVsyncObserver(aVsyncObserver)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
}
|
||||
|
||||
CompositorWidgetChild::~CompositorWidgetChild()
|
||||
|
@ -52,11 +59,26 @@ CompositorWidgetChild::ResizeTransparentWindow(const gfx::IntSize& aSize)
|
|||
Unused << SendResizeTransparentWindow(aSize);
|
||||
}
|
||||
|
||||
HDC CompositorWidgetChild::GetTransparentDC() const
|
||||
HDC
|
||||
CompositorWidgetChild::GetTransparentDC() const
|
||||
{
|
||||
// Not supported in out-of-process mode.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorWidgetChild::RecvObserveVsync()
|
||||
{
|
||||
mVsyncDispatcher->SetCompositorVsyncObserver(mVsyncObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorWidgetChild::RecvUnobserveVsync()
|
||||
{
|
||||
mVsyncDispatcher->SetCompositorVsyncObserver(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
|
||||
#include "WinCompositorWidget.h"
|
||||
#include "mozilla/widget/PCompositorWidgetChild.h"
|
||||
#include "mozilla/widget/CompositorWidgetVsyncObserver.h"
|
||||
|
||||
namespace mozilla {
|
||||
class CompositorVsyncDispatcher;
|
||||
|
||||
namespace widget {
|
||||
|
||||
class CompositorWidgetChild final
|
||||
|
@ -17,7 +20,8 @@ class CompositorWidgetChild final
|
|||
public CompositorWidgetDelegate
|
||||
{
|
||||
public:
|
||||
CompositorWidgetChild(nsIWidget* aWidget);
|
||||
CompositorWidgetChild(RefPtr<CompositorVsyncDispatcher> aVsyncDispatcher,
|
||||
RefPtr<CompositorWidgetVsyncObserver> aVsyncObserver);
|
||||
~CompositorWidgetChild() override;
|
||||
|
||||
void EnterPresentLock() override;
|
||||
|
@ -27,6 +31,13 @@ public:
|
|||
void ClearTransparentWindow() override;
|
||||
void ResizeTransparentWindow(const gfx::IntSize& aSize) override;
|
||||
HDC GetTransparentDC() const override;
|
||||
|
||||
bool RecvObserveVsync() override;
|
||||
bool RecvUnobserveVsync() override;
|
||||
|
||||
private:
|
||||
RefPtr<CompositorVsyncDispatcher> mVsyncDispatcher;
|
||||
RefPtr<CompositorWidgetVsyncObserver> mVsyncObserver;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace widget {
|
|||
CompositorWidgetParent::CompositorWidgetParent(const CompositorWidgetInitData& aInitData)
|
||||
: WinCompositorWidget(aInitData)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
|
||||
}
|
||||
|
||||
CompositorWidgetParent::~CompositorWidgetParent()
|
||||
|
@ -52,6 +53,30 @@ CompositorWidgetParent::RecvResizeTransparentWindow(const IntSize& aSize)
|
|||
return true;
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
CompositorWidgetParent::RealWidget()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorWidgetParent::ObserveVsync(VsyncObserver* aObserver)
|
||||
{
|
||||
if (aObserver) {
|
||||
SendObserveVsync();
|
||||
} else {
|
||||
SendUnobserveVsync();
|
||||
}
|
||||
mVsyncObserver = aObserver;
|
||||
}
|
||||
|
||||
RefPtr<VsyncObserver>
|
||||
CompositorWidgetParent::GetVsyncObserver() const
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
|
||||
return mVsyncObserver;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorWidgetParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,13 @@ public:
|
|||
bool RecvClearTransparentWindow() override;
|
||||
bool RecvResizeTransparentWindow(const IntSize& aSize) override;
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
nsIWidget* RealWidget() override;
|
||||
void ObserveVsync(VsyncObserver* aObserver) override;
|
||||
RefPtr<VsyncObserver> GetVsyncObserver() const override;
|
||||
|
||||
private:
|
||||
RefPtr<VsyncObserver> mVsyncObserver;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- 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 "InProcessWinCompositorWidget.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
/* static */ RefPtr<CompositorWidget>
|
||||
CompositorWidget::CreateLocal(const CompositorWidgetInitData& aInitData, nsIWidget* aWidget)
|
||||
{
|
||||
return new InProcessWinCompositorWidget(aInitData, static_cast<nsWindow*>(aWidget));
|
||||
}
|
||||
|
||||
InProcessWinCompositorWidget::InProcessWinCompositorWidget(const CompositorWidgetInitData& aInitData,
|
||||
nsWindow* aWindow)
|
||||
: WinCompositorWidget(aInitData),
|
||||
mWindow(aWindow)
|
||||
{
|
||||
MOZ_ASSERT(mWindow);
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
InProcessWinCompositorWidget::RealWidget()
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
void
|
||||
InProcessWinCompositorWidget::ObserveVsync(VsyncObserver* aObserver)
|
||||
{
|
||||
RefPtr<CompositorVsyncDispatcher> cvd = mWindow->GetCompositorVsyncDispatcher();
|
||||
cvd->SetCompositorVsyncObserver(aObserver);
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- 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 widget_windows_InProcessCompositorWidgetParent_h
|
||||
#define widget_windows_InProcessCompositorWidgetParent_h
|
||||
|
||||
#include "WinCompositorWidget.h"
|
||||
|
||||
class nsWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
// This is the Windows-specific implementation of CompositorWidget. For
|
||||
// the most part it only requires an HWND, however it maintains extra state
|
||||
// for transparent windows, as well as for synchronizing WM_SETTEXT messages
|
||||
// with the compositor.
|
||||
class InProcessWinCompositorWidget final : public WinCompositorWidget
|
||||
{
|
||||
public:
|
||||
InProcessWinCompositorWidget(const CompositorWidgetInitData& aInitData, nsWindow* aWindow);
|
||||
|
||||
void ObserveVsync(VsyncObserver* aObserver) override;
|
||||
nsIWidget* RealWidget() override;
|
||||
|
||||
private:
|
||||
nsWindow* mWindow;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // widget_windows_InProcessCompositorWidgetParent_h
|
|
@ -22,6 +22,10 @@ parent:
|
|||
sync ClearTransparentWindow();
|
||||
sync ResizeTransparentWindow(IntSize aSize);
|
||||
async __delete__();
|
||||
|
||||
child:
|
||||
async ObserveVsync();
|
||||
async UnobserveVsync();
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -4,26 +4,18 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WinCompositorWidget.h"
|
||||
#include "nsWindow.h"
|
||||
#include "VsyncDispatcher.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/widget/PlatformWidgetTypes.h"
|
||||
#include "nsWindow.h"
|
||||
#include "VsyncDispatcher.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
/* static */ RefPtr<CompositorWidget>
|
||||
CompositorWidget::CreateLocal(const CompositorWidgetInitData& aInitData, nsIWidget* aWidget)
|
||||
{
|
||||
return new WinCompositorWidget(aInitData, static_cast<nsWindow*>(aWidget));
|
||||
}
|
||||
|
||||
WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitData,
|
||||
nsWindow* aWindow)
|
||||
: mWindow(aWindow),
|
||||
mWidgetKey(aInitData.widgetKey()),
|
||||
WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitData)
|
||||
: mWidgetKey(aInitData.widgetKey()),
|
||||
mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
|
||||
mTransparencyMode(static_cast<nsTransparencyMode>(aInitData.transparencyMode())),
|
||||
mMemoryDC(nullptr),
|
||||
|
@ -57,13 +49,6 @@ WinCompositorWidget::PostRender(layers::LayerManagerComposite* aManager)
|
|||
mPresentLock.Leave();
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
WinCompositorWidget::RealWidget()
|
||||
{
|
||||
MOZ_ASSERT(mWindow);
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
LayoutDeviceIntSize
|
||||
WinCompositorWidget::GetClientSize()
|
||||
{
|
||||
|
@ -173,13 +158,6 @@ WinCompositorWidget::EndBackBufferDrawing()
|
|||
return CompositorWidget::EndBackBufferDrawing();
|
||||
}
|
||||
|
||||
void
|
||||
WinCompositorWidget::ObserveVsync(VsyncObserver* aObserver)
|
||||
{
|
||||
RefPtr<CompositorVsyncDispatcher> cvd = mWindow->GetCompositorVsyncDispatcher();
|
||||
cvd->SetCompositorVsyncObserver(aObserver);
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
WinCompositorWidget::GetWidgetKey()
|
||||
{
|
||||
|
|
|
@ -46,8 +46,7 @@ class WinCompositorWidget
|
|||
public CompositorWidgetDelegate
|
||||
{
|
||||
public:
|
||||
WinCompositorWidget(const CompositorWidgetInitData& aInitData,
|
||||
nsWindow* aWindow = nullptr);
|
||||
WinCompositorWidget(const CompositorWidgetInitData& aInitData);
|
||||
|
||||
bool PreRender(layers::LayerManagerComposite*) override;
|
||||
void PostRender(layers::LayerManagerComposite*) override;
|
||||
|
@ -58,9 +57,7 @@ public:
|
|||
const LayoutDeviceIntRect& aRect,
|
||||
const LayoutDeviceIntRect& aClearRect) override;
|
||||
already_AddRefed<gfx::SourceSurface> EndBackBufferDrawing() override;
|
||||
void ObserveVsync(VsyncObserver* aObserver) override;
|
||||
uintptr_t GetWidgetKey() override;
|
||||
nsIWidget* RealWidget() override;
|
||||
WinCompositorWidget* AsWindows() override {
|
||||
return this;
|
||||
}
|
||||
|
@ -95,7 +92,6 @@ private:
|
|||
void CreateTransparentSurface(const gfx::IntSize& aSize);
|
||||
|
||||
private:
|
||||
nsWindow* mWindow;
|
||||
uintptr_t mWidgetKey;
|
||||
HWND mWnd;
|
||||
gfx::CriticalSection mPresentLock;
|
||||
|
|
|
@ -16,6 +16,7 @@ EXPORTS.mozilla.widget += [
|
|||
'AudioSession.h',
|
||||
'CompositorWidgetChild.h',
|
||||
'CompositorWidgetParent.h',
|
||||
'InProcessWinCompositorWidget.h',
|
||||
'WinCompositorWidget.h',
|
||||
'WinMessages.h',
|
||||
'WinModifierKeyState.h',
|
||||
|
@ -30,6 +31,7 @@ UNIFIED_SOURCES += [
|
|||
'IEnumFE.cpp',
|
||||
'IMMHandler.cpp',
|
||||
'InkCollector.cpp',
|
||||
'InProcessWinCompositorWidget.cpp',
|
||||
'JumpListItem.cpp',
|
||||
'KeyboardLayout.cpp',
|
||||
'nsAppShell.cpp',
|
||||
|
|
|
@ -141,7 +141,7 @@
|
|||
#include "nsBidiKeyboard.h"
|
||||
#include "nsThemeConstants.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "WinCompositorWidget.h"
|
||||
#include "InProcessWinCompositorWidget.h"
|
||||
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsUXThemeConstants.h"
|
||||
|
@ -3732,7 +3732,7 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
|||
reinterpret_cast<uintptr_t>(mWnd),
|
||||
reinterpret_cast<uintptr_t>(static_cast<nsIWidget*>(this)),
|
||||
mTransparencyMode);
|
||||
mBasicLayersSurface = new WinCompositorWidget(initData, this);
|
||||
mBasicLayersSurface = new InProcessWinCompositorWidget(initData, this);
|
||||
mCompositorWidgetDelegate = mBasicLayersSurface;
|
||||
mLayerManager = CreateBasicLayerManager();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче