gfx/layers/composite/CompositableHost.h
author Hiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 31 Jul 2018 06:13:15 +0900
changeset 429281 23119363c98a566674fb87148fa006c37536beea
parent 429237 775c7c08f6fd3cb3e9d53a889f7860654cf60c9a
child 432913 3e0995cbb3dfb2a87dbe00aed20be7c6b7685ccb
permissions -rw-r--r--
Bug 1479234 - Fix the header for gfx::Glyph. r=kats MozReview-Commit-ID: I0ukIwuxv7z

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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_GFX_BUFFERHOST_H
#define MOZILLA_GFX_BUFFERHOST_H

#include <stdint.h>                     // for uint64_t
#include <stdio.h>                      // for FILE
#include "gfxRect.h"                    // for gfxRect
#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h"         // for override
#include "mozilla/RefPtr.h"             // for RefPtr, RefCounted, etc
#include "mozilla/gfx/MatrixFwd.h"      // for Matrix4x4
#include "mozilla/gfx/Point.h"          // for Point
#include "mozilla/gfx/Polygon.h"        // for Polygon
#include "mozilla/gfx/Rect.h"           // for Rect
#include "mozilla/gfx/Types.h"          // for SamplingFilter
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/Compositor.h"  // for Compositor
#include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
#include "mozilla/layers/Effects.h"     // for Texture Effect
#include "mozilla/layers/LayersTypes.h"  // for LayerRenderState, etc
#include "mozilla/layers/LayersMessages.h"
#include "mozilla/layers/TextureHost.h" // for TextureHost
#include "mozilla/mozalloc.h"           // for operator delete
#include "nsCOMPtr.h"                   // for already_AddRefed
#include "nsRegion.h"                   // for nsIntRegion
#include "nscore.h"                     // for nsACString
#include "Units.h"                      // for CSSToScreenScale

namespace mozilla {
namespace gfx {
class DataSourceSurface;
} // namespace gfx

namespace layers {

class Layer;
class LayerComposite;
class ImageHost;
class Compositor;
class ThebesBufferData;
class TiledContentHost;
class CompositableParentManager;
class WebRenderImageHost;
class ContentHost;
class ContentHostTexture;
class HostLayerManager;
struct EffectChain;

struct ImageCompositeNotificationInfo {
  base::ProcessId mImageBridgeProcessId;
  ImageCompositeNotification mNotification;
};

struct AsyncCompositableRef
{
  AsyncCompositableRef()
   : mProcessId(mozilla::ipc::kInvalidProcessId)
  {}
  AsyncCompositableRef(base::ProcessId aProcessId, const CompositableHandle& aHandle)
   : mProcessId(aProcessId), mHandle(aHandle)
  {}
  explicit operator bool() const { return !!mHandle; }
  base::ProcessId mProcessId;
  CompositableHandle mHandle;
};

/**
 * The compositor-side counterpart to CompositableClient. Responsible for
 * updating textures and data about textures from IPC and how textures are
 * composited (tiling, double buffering, etc.).
 *
 * Update (for images/canvases) and UpdateThebes (for Thebes) are called during
 * the layers transaction to update the Compositbale's textures from the
 * content side. The actual update (and any syncronous upload) is done by the
 * TextureHost, but it is coordinated by the CompositableHost.
 *
 * Composite is called by the owning layer when it is composited. CompositableHost
 * will use its TextureHost(s) and call Compositor::DrawQuad to do the actual
 * rendering.
 */
class CompositableHost
{
protected:
  virtual ~CompositableHost();

public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositableHost)
  explicit CompositableHost(const TextureInfo& aTextureInfo);

  static already_AddRefed<CompositableHost> Create(const TextureInfo& aTextureInfo, bool aUseWebRender);

  virtual CompositableType GetType() = 0;

  // If base class overrides, it should still call the parent implementation
  virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider);

  // composite the contents of this buffer host to the compositor's surface
  virtual void Composite(Compositor* aCompositor,
                         LayerComposite* aLayer,
                         EffectChain& aEffectChain,
                         float aOpacity,
                         const gfx::Matrix4x4& aTransform,
                         const gfx::SamplingFilter aSamplingFilter,
                         const gfx::IntRect& aClipRect,
                         const nsIntRegion* aVisibleRegion = nullptr,
                         const Maybe<gfx::Polygon>& aGeometry = Nothing()) = 0;

  /**
   * Update the content host.
   * aUpdated is the region which should be updated.
   */
  virtual bool UpdateThebes(const ThebesBufferData& aData,
                            const nsIntRegion& aUpdated,
                            const nsIntRegion& aOldValidRegionBack)
  {
    NS_ERROR("should be implemented or not used");
    return false;
  }

  /**
   * Returns the front buffer.
   * *aPictureRect (if non-null, and the returned TextureHost is non-null)
   * is set to the picture rect.
   */
  virtual TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) {
    return nullptr;
  }

  virtual gfx::IntSize GetImageSize() const
  {
    MOZ_ASSERT(false, "Should have been overridden");
    return gfx::IntSize();
  }

  /**
   * Adds a mask effect using this texture as the mask, if possible.
   * @return true if the effect was added, false otherwise.
   */
  bool AddMaskEffect(EffectChain& aEffects,
                     const gfx::Matrix4x4& aTransform);

  void RemoveMaskEffect();

  TextureSourceProvider* GetTextureSourceProvider() const;

  Layer* GetLayer() const { return mLayer; }
  void SetLayer(Layer* aLayer) { mLayer = aLayer; }

  virtual ContentHost* AsContentHost() { return nullptr; }
  virtual ContentHostTexture* AsContentHostTexture() { return nullptr; }
  virtual ImageHost* AsImageHost() { return nullptr; }
  virtual TiledContentHost* AsTiledContentHost() { return nullptr; }
  virtual WebRenderImageHost* AsWebRenderImageHost() { return nullptr; }

  typedef uint32_t AttachFlags;
  static const AttachFlags NO_FLAGS = 0;
  static const AttachFlags ALLOW_REATTACH = 1;
  static const AttachFlags KEEP_ATTACHED = 2;
  static const AttachFlags FORCE_DETACH = 2;

  virtual void Attach(Layer* aLayer,
                      TextureSourceProvider* aProvider,
                      AttachFlags aFlags = NO_FLAGS)
  {
    MOZ_ASSERT(aProvider);
    NS_ASSERTION(aFlags & ALLOW_REATTACH || !mAttached,
                 "Re-attaching compositables must be explicitly authorised");
    SetTextureSourceProvider(aProvider);
    SetLayer(aLayer);
    mAttached = true;
    mKeepAttached = aFlags & KEEP_ATTACHED;
  }
  // Detach this compositable host from its layer.
  // If we are used for async video, then it is not safe to blindly detach since
  // we might be re-attached to a different layer. aLayer is the layer which the
  // caller expects us to be attached to, we will only detach if we are in fact
  // attached to that layer. If we are part of a normal layer, then we will be
  // detached in any case. if aLayer is null, then we will only detach if we are
  // not async.
  // Only force detach if the IPDL tree is being shutdown.
  virtual void Detach(Layer* aLayer = nullptr, AttachFlags aFlags = NO_FLAGS)
  {
    if (!mKeepAttached ||
        aLayer == mLayer ||
        aFlags & FORCE_DETACH) {
      SetLayer(nullptr);
      mAttached = false;
      mKeepAttached = false;
    }
  }
  bool IsAttached() { return mAttached; }

  virtual void Dump(std::stringstream& aStream,
                    const char* aPrefix="",
                    bool aDumpHtml=false) { }
  static void DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture);

  virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }

  virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0;

  struct TimedTexture {
    CompositableTextureHostRef mTexture;
    TimeStamp mTimeStamp;
    gfx::IntRect mPictureRect;
    int32_t mFrameID;
    int32_t mProducerID;
  };
  virtual void UseTextureHost(const nsTArray<TimedTexture>& aTextures);
  virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
                                         TextureHost* aTextureOnWhite);
  virtual void RemoveTextureHost(TextureHost* aTexture);

  // Called every time this is composited
  void BumpFlashCounter() {
    mFlashCounter = mFlashCounter >= DIAGNOSTIC_FLASH_COUNTER_MAX
                  ? DIAGNOSTIC_FLASH_COUNTER_MAX : mFlashCounter + 1;
  }

  uint64_t GetCompositorBridgeID() const { return mCompositorBridgeID; }

  const AsyncCompositableRef& GetAsyncRef() const { return mAsyncRef; }
  void SetAsyncRef(const AsyncCompositableRef& aRef) { mAsyncRef = aRef; }

  void SetCompositorBridgeID(uint64_t aID) { mCompositorBridgeID = aID; }

  virtual bool Lock() { return false; }

  virtual void Unlock() { }

  virtual already_AddRefed<TexturedEffect> GenEffect(const gfx::SamplingFilter aSamplingFilter) {
    return nullptr;
  }

  /// Called when shutting down the layer tree.
  /// This is a good place to clear all potential gpu resources before the widget
  /// is is destroyed.
  virtual void CleanupResources() {}

  virtual void BindTextureSource() {}

protected:
  HostLayerManager* GetLayerManager() const;

protected:
  TextureInfo mTextureInfo;
  AsyncCompositableRef mAsyncRef;
  uint64_t mCompositorBridgeID;
  RefPtr<TextureSourceProvider> mTextureSourceProvider;
  Layer* mLayer;
  uint32_t mFlashCounter; // used when the pref "layers.flash-borders" is true.
  bool mAttached;
  bool mKeepAttached;
};

class AutoLockCompositableHost final
{
public:
  explicit AutoLockCompositableHost(CompositableHost* aHost)
    : mHost(aHost)
  {
    mSucceeded = (mHost && mHost->Lock());
  }

  ~AutoLockCompositableHost()
  {
    if (mSucceeded && mHost) {
      mHost->Unlock();
    }
  }

  bool Failed() const { return !mSucceeded; }

private:
  RefPtr<CompositableHost> mHost;
  bool mSucceeded;
};

} // namespace layers
} // namespace mozilla

#endif