Commit d93d452a authored by Matt Woodrow's avatar Matt Woodrow
Browse files

Bug 1727672 - Remove LayerManagerComposite. r=jrmuizel

parent d751b431
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -130,7 +130,6 @@ class TextureSource;
class DataTextureSource;
class CompositingRenderTarget;
class CompositorBridgeParent;
class LayerManagerComposite;
class NativeLayer;
class CompositorOGL;
class CompositorD3D11;
+3 −336
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@
#include "mozilla/layers/APZSampler.h"              // for APZSampler
#include "mozilla/layers/CompositorBridgeParent.h"  // for CompositorBridgeParent
#include "mozilla/layers/CompositorThread.h"     // for CompositorThreadHolder
#include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite, etc
#include "mozilla/layers/LayerMetricsWrapper.h"  // for LayerMetricsWrapper
#include "mozilla/layers/OMTAController.h"       // for OMTAController
#include "mozilla/ScopeExit.h"
@@ -341,337 +340,5 @@ WrAnimations CompositorAnimationStorage::CollectWebRenderAnimations() const {
  return animations;
}

static gfx::Matrix4x4 FrameTransformToTransformInDevice(
    const gfx::Matrix4x4& aFrameTransform, Layer* aLayer,
    const TransformData& aTransformData) {
  gfx::Matrix4x4 transformInDevice = aFrameTransform;
  // If our parent layer is a perspective layer, then the offset into reference
  // frame coordinates is already on that layer. If not, then we need to ask
  // for it to be added here.
  if (!aLayer->GetParent() ||
      !aLayer->GetParent()->GetTransformIsPerspective()) {
    nsLayoutUtils::PostTranslate(
        transformInDevice, aTransformData.origin(),
        aTransformData.appUnitsPerDevPixel(),
        aLayer->GetContentFlags() & Layer::CONTENT_SNAP_TO_GRID);
  }

  if (ContainerLayer* c = aLayer->AsContainerLayer()) {
    transformInDevice.PostScale(c->GetInheritedXScale(),
                                c->GetInheritedYScale(), 1);
  }

  return transformInDevice;
}

static Matrix4x4 GetTransformForPartialPrerender(
    Layer* aLayer, const LayersId aLayersId,
    const ScrollableLayerGuid::ViewID& aScrollId,
    const RefPtr<APZSampler>& aSampler) {
  MOZ_ASSERT(aLayer);

  ParentLayerPoint translationByApz;
  Matrix4x4 transform;

  for (Layer* layer = aLayer; layer; layer = layer->GetParent()) {
    if (layer->AsRefLayer()) {
      MOZ_ASSERT(layer->AsRefLayer()->GetReferentId() == aLayersId);
      break;
    }

    // Accumulate static transforms.
    if (layer != aLayer) {
      Matrix4x4 baseTransform = layer->GetBaseTransform();
      if (ContainerLayer* container = layer->AsContainerLayer()) {
        baseTransform.PostScale(container->GetPreXScale(),
                                container->GetPreYScale(), 1);
      }
      transform *= baseTransform;
    }

    if (!layer->GetIsStickyPosition() && !layer->GetIsFixedPosition()) {
      bool hasSameScrollId = false;
      for (uint32_t i = 0; i < layer->GetScrollMetadataCount(); i++) {
        // Factor APZ translation if there exists.
        if (aSampler) {
          LayerMetricsWrapper wrapper = LayerMetricsWrapper(layer, i);
          AsyncTransform asyncTransform =
              aSampler->GetCurrentAsyncTransform(wrapper, LayoutAndVisual);
          translationByApz += asyncTransform.mTranslation;
        }
        if (layer->GetFrameMetrics(i).GetScrollId() == aScrollId) {
          hasSameScrollId = true;
        }
      }

      if (hasSameScrollId) {
        break;
      }
    } else {
      // Bug 1642547: Fix for position:sticky layers.
    }
  }

  transform.PostTranslate(translationByApz.ToUnknownPoint());

  return transform;
}

bool CompositorAnimationStorage::ApplyAnimatedValue(
    CompositorBridgeParent* aCompositorBridge, Layer* aLayer,
    nsCSSPropertyID aProperty, AnimatedValue* aPreviousValue,
    const nsTArray<RefPtr<RawServoAnimationValue>>& aValues) {
  mLock.AssertCurrentThreadOwns();

  MOZ_ASSERT(!aValues.IsEmpty());

  bool janked = false;
  HostLayer* layerCompositor = aLayer->AsHostLayer();
  switch (aProperty) {
    case eCSSProperty_background_color: {
      MOZ_ASSERT(aValues.Length() == 1);
      // We don't support 'color' animations on the compositor yet so we never
      // meet currentColor on the compositor.
      nscolor color =
          Servo_AnimationValue_GetColor(aValues[0], NS_RGBA(0, 0, 0, 0));
      aLayer->AsColorLayer()->SetColor(gfx::ToDeviceColor(color));
      SetAnimatedValue(aLayer->GetCompositorAnimationsId(), aPreviousValue,
                       color);

      layerCompositor->SetShadowOpacity(aLayer->GetOpacity());
      layerCompositor->SetShadowOpacitySetByAnimation(false);
      layerCompositor->SetShadowBaseTransform(aLayer->GetBaseTransform());
      layerCompositor->SetShadowTransformSetByAnimation(false);
      break;
    }
    case eCSSProperty_opacity: {
      MOZ_ASSERT(aValues.Length() == 1);
      float opacity = Servo_AnimationValue_GetOpacity(aValues[0]);
      layerCompositor->SetShadowOpacity(opacity);
      layerCompositor->SetShadowOpacitySetByAnimation(true);
      SetAnimatedValue(aLayer->GetCompositorAnimationsId(), aPreviousValue,
                       opacity);

      layerCompositor->SetShadowBaseTransform(aLayer->GetBaseTransform());
      layerCompositor->SetShadowTransformSetByAnimation(false);
      break;
    }
    case eCSSProperty_rotate:
    case eCSSProperty_scale:
    case eCSSProperty_translate:
    case eCSSProperty_transform:
    case eCSSProperty_offset_path:
    case eCSSProperty_offset_distance:
    case eCSSProperty_offset_rotate:
    case eCSSProperty_offset_anchor: {
      MOZ_ASSERT(aLayer->GetTransformData());
      const TransformData& transformData = *aLayer->GetTransformData();
      gfx::Matrix4x4 frameTransform =
          AnimationHelper::ServoAnimationValueToMatrix4x4(
              aValues, transformData, aLayer->CachedMotionPath());

      gfx::Matrix4x4 transform = FrameTransformToTransformInDevice(
          frameTransform, aLayer, transformData);
      if (const Maybe<PartialPrerenderData>& partialPrerenderData =
              transformData.partialPrerenderData()) {
        Matrix4x4 transformInClip = GetTransformForPartialPrerender(
            aLayer, aLayer->GetAnimationLayersId(),
            partialPrerenderData->scrollId(),
            aCompositorBridge->GetAPZSampler());
        transformInClip = transform * transformInClip;
        ParentLayerRect clipRect = GetClipRectForPartialPrerender(
            aLayer->GetAnimationLayersId(), *partialPrerenderData,
            aCompositorBridge->GetAPZSampler());
        if (AnimationHelper::ShouldBeJank(
                partialPrerenderData->rect(),
                partialPrerenderData->overflowedSides(), transformInClip,
                clipRect)) {
          // It's possible that we don't have the previous value and we don't
          // either have enough area to composite in the first composition,
          // e.g. a translate animation with a step timing function.  In such
          // cases we use the base transform value which was calculated on the
          // main-thread as a fallback value.
          transform = aPreviousValue
                          ? aPreviousValue->Transform().mTransformInDevSpace
                          : aLayer->GetBaseTransform();
          janked = true;
        }
      }

      layerCompositor->SetShadowBaseTransform(transform);
      layerCompositor->SetShadowTransformSetByAnimation(true);
      SetAnimatedValue(aLayer->GetCompositorAnimationsId(), aPreviousValue,
                       transform, frameTransform, transformData);

      layerCompositor->SetShadowOpacity(aLayer->GetOpacity());
      layerCompositor->SetShadowOpacitySetByAnimation(false);
      break;
    }
    default:
      MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
  }
  return !janked;
}

bool CompositorAnimationStorage::SampleAnimations(
    Layer* aRoot, CompositorBridgeParent* aCompositorBridge,
    TimeStamp aPreviousFrameTime, TimeStamp aCurrentFrameTime) {
  MutexAutoLock lock(mLock);

  bool isAnimating = false;

  auto autoClearAnimationStorage = MakeScopeExit([&] {
    if (!isAnimating) {
      // Clean up the CompositorAnimationStorage because
      // there are no active animations running
      Clear();
    }
  });

  std::unordered_map<LayersId, nsTArray<uint64_t>, LayersId::HashFn> janked;

  ForEachNode<ForwardIterator>(aRoot, [&](Layer* layer) {
    auto& propertyAnimationGroups = layer->GetPropertyAnimationGroups();
    if (propertyAnimationGroups.IsEmpty()) {
      return;
    }

    isAnimating = true;
    AnimatedValue* previousValue =
        GetAnimatedValue(layer->GetCompositorAnimationsId());

    AutoTArray<RefPtr<RawServoAnimationValue>, 1> animationValues;
    AnimationHelper::SampleResult sampleResult =
        AnimationHelper::SampleAnimationForEachNode(
            aPreviousFrameTime, aCurrentFrameTime, previousValue,
            propertyAnimationGroups, animationValues);

    const PropertyAnimationGroup& lastPropertyAnimationGroup =
        propertyAnimationGroups.LastElement();

    switch (sampleResult) {
      case AnimationHelper::SampleResult::Sampled:
        // We assume all transform like properties (on the same frame) live in
        // a single same layer, so using the transform data of the last element
        // should be fine.
        if (!ApplyAnimatedValue(aCompositorBridge, layer,
                                lastPropertyAnimationGroup.mProperty,
                                previousValue, animationValues)) {
          // Reset the last composition values in cases of jank so that we will
          // never mis-compare in a sanity check in the case of
          // SampleResult::Skipped below in this function.
          //
          // An example;
          // a translateX(0px) -> translateX(100px) animation with step(2,start)
          // and if the animation janked at translateX(50px) and in a later
          // frame if the calculated transform value is going to be still
          // translateX(50px) (i.e. at the same timing portion calculated by the
          // step timing function), we skip sampling. That's correct ideally.
          // But we have an assertion to do a sanity check for the skip sampling
          // case that the check compares the calculated value translateX(50px)
          // with the previous composited value. In this case the previous
          // composited value is translateX(0px).
          //
          // NOTE: Ideally we shouldn't update the last composition values when
          // we met janks, but it's quite hard to tell whether the jank will
          // happen or not when we calculate each transform like properties'
          // value (i.e. when we set the last composition value) since janks are
          // caused by a result of the combinations of all transform like
          // properties (e.g. `transform: translateX(50px)` and
          // `translate: -50px` results `translateX(0px)`.
          for (PropertyAnimationGroup& group : propertyAnimationGroups) {
            group.ResetLastCompositionValues();
          }
          janked[layer->GetAnimationLayersId()].AppendElement(
              layer->GetCompositorAnimationsId());
        }
        break;
      case AnimationHelper::SampleResult::Skipped:
        switch (lastPropertyAnimationGroup.mProperty) {
          case eCSSProperty_background_color:
          case eCSSProperty_opacity: {
            if (lastPropertyAnimationGroup.mProperty == eCSSProperty_opacity) {
              MOZ_ASSERT(
                  layer->AsHostLayer()->GetShadowOpacitySetByAnimation());
#ifdef DEBUG
              // Disable this assertion until the root cause is fixed in bug
              // 1459775.
              // MOZ_ASSERT(FuzzyEqualsMultiplicative(
              //   Servo_AnimationValue_GetOpacity(animationValue),
              //   *(GetAnimationOpacity(layer->GetCompositorAnimationsId()))));
#endif
            }
            // Even if opacity or background-color  animation value has
            // unchanged, we have to set the shadow base transform value
            // here since the value might have been changed by APZC.
            HostLayer* layerCompositor = layer->AsHostLayer();
            layerCompositor->SetShadowBaseTransform(layer->GetBaseTransform());
            layerCompositor->SetShadowTransformSetByAnimation(false);
            break;
          }
          case eCSSProperty_rotate:
          case eCSSProperty_scale:
          case eCSSProperty_translate:
          case eCSSProperty_transform:
          case eCSSProperty_offset_path:
          case eCSSProperty_offset_distance:
          case eCSSProperty_offset_rotate:
          case eCSSProperty_offset_anchor: {
            MOZ_ASSERT(
                layer->AsHostLayer()->GetShadowTransformSetByAnimation());
            MOZ_ASSERT(previousValue);
            MOZ_ASSERT(layer->GetTransformData());
#ifdef DEBUG
            gfx::Matrix4x4 frameTransform =
                AnimationHelper::ServoAnimationValueToMatrix4x4(
                    animationValues, *layer->GetTransformData(),
                    layer->CachedMotionPath());
            gfx::Matrix4x4 transformInDevice =
                FrameTransformToTransformInDevice(frameTransform, layer,
                                                  *layer->GetTransformData());
            MOZ_ASSERT(previousValue->Transform()
                           .mTransformInDevSpace.FuzzyEqualsMultiplicative(
                               transformInDevice));
#endif
            // In the case of transform we have to set the unchanged
            // transform value again because APZC might have modified the
            // previous shadow base transform value.
            HostLayer* layerCompositor = layer->AsHostLayer();
            layerCompositor->SetShadowBaseTransform(
                // FIXME: Bug 1459775: It seems possible that we somehow try
                // to sample animations and skip it even if the previous value
                // has been discarded from the animation storage when we enable
                // layer tree cache. So for the safety, in the case where we
                // have no previous animation value, we set non-animating value
                // instead.
                previousValue ? previousValue->Transform().mTransformInDevSpace
                              : layer->GetBaseTransform());
            break;
          }
          default:
            MOZ_ASSERT_UNREACHABLE("Unsupported properties");
            break;
        }
        break;
      case AnimationHelper::SampleResult::None: {
        HostLayer* layerCompositor = layer->AsHostLayer();
        layerCompositor->SetShadowBaseTransform(layer->GetBaseTransform());
        layerCompositor->SetShadowTransformSetByAnimation(false);
        layerCompositor->SetShadowOpacity(layer->GetOpacity());
        layerCompositor->SetShadowOpacitySetByAnimation(false);
        break;
      }
      default:
        break;
    }
  });

  if (!janked.empty()) {
    aCompositorBridge->NotifyJankedAnimations(janked);
  }

  return isAnimating;
}

}  // namespace layers
}  // namespace mozilla
+0 −15
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ namespace mozilla {
namespace layers {
class Animation;
class CompositorBridgeParent;
class Layer;
class OMTAController;

typedef nsTArray<layers::Animation> AnimationArray;
@@ -157,15 +156,6 @@ class CompositorAnimationStorage final {
                        TimeStamp aPreviousFrameTime,
                        TimeStamp aCurrentFrameTime);

  /**
   * Non WebRender version of above SampleAnimations.
   *
   * Note: This is called only by non WebRender.
   */
  bool SampleAnimations(Layer* aRoot, CompositorBridgeParent* aCompositorBridge,
                        TimeStamp aPreviousFrameTime,
                        TimeStamp aCurrentFrameTime);

  bool HasAnimations() const;

  /**
@@ -214,11 +204,6 @@ class CompositorAnimationStorage final {
  void SetAnimatedValue(uint64_t aId, AnimatedValue* aPreviousValue,
                        nscolor aColor);

  bool ApplyAnimatedValue(
      CompositorBridgeParent* aCompositorBridge, Layer* aLayer,
      nsCSSPropertyID aProperty, AnimatedValue* aPreviousValue,
      const nsTArray<RefPtr<RawServoAnimationValue>>& aValues);

  void Clear();

 private:
+0 −6
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ namespace layers {

class AsyncPanZoomController;
class ClientLayerManager;
class HostLayerManager;
class Layer;
class LayerMetricsWrapper;
class PaintedLayer;
@@ -72,7 +71,6 @@ class RefLayer;
class HostLayer;
class FocusTarget;
class KnowsCompositor;
class LayerManagerComposite;
class TransactionIdAllocator;
class FrameUniformityData;
class PersistentBufferProvider;
@@ -160,10 +158,6 @@ class LayerManager : public WindowRenderer {

  virtual LayerManager* AsLayerManager() override { return this; }

  virtual LayerManagerComposite* AsLayerManagerComposite() { return nullptr; }

  virtual HostLayerManager* AsHostLayerManager() { return nullptr; }

  virtual WebRenderLayerManager* AsWebRenderLayerManager() { return nullptr; }

  /**
+0 −63
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@

#include "mozilla/layers/CompositorOGL.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/TextureHostOGL.h"

#include "gfxContext.h"
@@ -741,8 +740,6 @@ NS_IMPL_ISUPPORTS(DebugDataSender::SendTask, nsIRunnable);
class SenderHelper {
  // Sender public APIs
 public:
  static void SendLayer(LayerComposite* aLayer, int aWidth, int aHeight);

  static void SendEffectChain(gl::GLContext* aGLContext,
                              const EffectChain& aEffectChain, int aWidth = 0,
                              int aHeight = 0);
@@ -796,47 +793,6 @@ bool SenderHelper::HasTextureIdBeenSent(GLuint aTextureId) {
                   aTextureId) != sSentTextureIds.end();
}

void SenderHelper::SendLayer(LayerComposite* aLayer, int aWidth, int aHeight) {
  MOZ_ASSERT(aLayer && aLayer->GetLayer());
  if (!aLayer || !aLayer->GetLayer()) {
    return;
  }

  switch (aLayer->GetLayer()->GetType()) {
    case Layer::TYPE_COLOR: {
      EffectChain effect;
      aLayer->GenEffectChain(effect);

      LayerScope::DrawBegin();
      LayerScope::DrawEnd(nullptr, effect, aWidth, aHeight);
      break;
    }
    case Layer::TYPE_IMAGE:
    case Layer::TYPE_CANVAS:
    case Layer::TYPE_PAINTED: {
      // Get CompositableHost and Compositor
      CompositableHost* compHost = aLayer->GetCompositableHost();
      TextureSourceProvider* provider = compHost->GetTextureSourceProvider();
      Compositor* comp = provider->AsCompositor();
      // Send EffectChain only for CompositorOGL
      if (LayersBackend::LAYERS_OPENGL == comp->GetBackendType()) {
        CompositorOGL* compOGL = comp->AsCompositorOGL();
        EffectChain effect;
        // Generate primary effect (lock and gen)
        AutoLockCompositableHost lock(compHost);
        aLayer->GenEffectChain(effect);

        LayerScope::DrawBegin();
        LayerScope::DrawEnd(compOGL->gl(), effect, aWidth, aHeight);
      }
      break;
    }
    case Layer::TYPE_CONTAINER:
    default:
      break;
  }
}

void SenderHelper::SendColor(void* aLayerRef, const DeviceColor& aColor,
                             int aWidth, int aHeight) {
  gLayerScopeManager.GetSocketManager()->AppendDebugData(
@@ -1540,25 +1496,6 @@ void LayerScope::DrawEnd(gl::GLContext* aGLContext,
                          draws.mTexIDs, aEffectChain.mLayerRef));
}

/*static*/
void LayerScope::SendLayer(LayerComposite* aLayer, int aWidth, int aHeight) {
  // Protect this public function
  if (!CheckSendable()) {
    return;
  }
  SenderHelper::SendLayer(aLayer, aWidth, aHeight);
}

/*static*/
void LayerScope::SendLayerDump(UniquePtr<Packet> aPacket) {
  // Protect this public function
  if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
    return;
  }
  gLayerScopeManager.GetSocketManager()->AppendDebugData(
      new DebugGLLayersData(std::move(aPacket)));
}

/*static*/
bool LayerScope::CheckSendable() {
  // Only compositor threads check LayerScope status
Loading