widget/VsyncDispatcher.h
author Chris H-C <chutten@mozilla.com>
Mon, 04 Jul 2016 11:16:05 -0400
changeset 312997 df28918fe2361f0b54ca9ce4773a29c4c0675d06
parent 305742 3fdb8ca3e6ffbd310daf342eb8febb1c17938dd0
permissions -rw-r--r--
bug 1218576 - Support remote accumulation via JS histograms. r=gfritzsche The JS histograms, too, need to dispatch their accumulations from child to parent. JSHistograms_Add now only supports histograms that are in gHistogramsMap or that were created in the parent process. After bug 1288745, maybe we'll be able to change this to be less convoluted. MozReview-Commit-ID: 3qTH89YKbGP

/* -*- 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 mozilla_widget_VsyncDispatcher_h
#define mozilla_widget_VsyncDispatcher_h

#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
#include "mozilla/RefPtr.h"

namespace mozilla {

class VsyncObserver
{
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncObserver)

public:
  // The method called when a vsync occurs. Return true if some work was done.
  // In general, this vsync notification will occur on the hardware vsync
  // thread from VsyncSource. But it might also be called on PVsync ipc thread
  // if this notification is cross process. Thus all observer should check the
  // thread model before handling the real task.
  virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;

protected:
  VsyncObserver() {}
  virtual ~VsyncObserver() {}
}; // VsyncObserver

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

public:
  CompositorVsyncDispatcher();

  // Called on the vsync thread when a hardware vsync occurs
  void NotifyVsync(TimeStamp aVsyncTimestamp);

  // Compositor vsync observers must be added/removed on the compositor thread
  void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
  void Shutdown();

private:
  virtual ~CompositorVsyncDispatcher();
  void ObserveVsync(bool aEnable);

  Mutex mCompositorObserverLock;
  RefPtr<VsyncObserver> mCompositorVsyncObserver;
  bool mDidShutdown;
};

// Dispatch vsync event to ipc actor parent and chrome RefreshTimer.
class RefreshTimerVsyncDispatcher final
{
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefreshTimerVsyncDispatcher)

public:
  RefreshTimerVsyncDispatcher();

  // Please check CompositorVsyncDispatcher::NotifyVsync().
  void NotifyVsync(TimeStamp aVsyncTimestamp);

  // Set chrome process's RefreshTimer to this dispatcher.
  // This function can be called from any thread.
  void SetParentRefreshTimer(VsyncObserver* aVsyncObserver);

  // Add or remove the content process' RefreshTimer to this dispatcher. This
  // will be a no-op for AddChildRefreshTimer() if the observer is already
  // registered.
  // These functions can be called from any thread.
  void AddChildRefreshTimer(VsyncObserver* aVsyncObserver);
  void RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver);

private:
  virtual ~RefreshTimerVsyncDispatcher();
  void UpdateVsyncStatus();
  bool NeedsVsync();

  Mutex mRefreshTimersLock;
  RefPtr<VsyncObserver> mParentRefreshTimer;
  nsTArray<RefPtr<VsyncObserver>> mChildRefreshTimers;
};

} // namespace mozilla

#endif // mozilla_widget_VsyncDispatcher_h