Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/layers/wr/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 8 kB image not shown  

Quelle  OMTASampler.cpp   Sprache: C

 
/* -*- 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/. */


#include "mozilla/layers/OMTASampler.h"

#include "mozilla/ClearOnShutdown.h"
#include "mozilla/layers/CompositorAnimationStorage.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/OMTAController.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/webrender/WebRenderAPI.h"

namespace mozilla {
namespace layers {

StaticMutex OMTASampler::sWindowIdLock;
StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<OMTASampler>>>
    OMTASampler::sWindowIdMap;

OMTASampler::OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage,
                         LayersId aRootLayersId)
    : mAnimStorage(aAnimStorage),
      mStorageLock("OMTASampler::mStorageLock"),
      mThreadIdLock("OMTASampler::mThreadIdLock"),
      mSampleTimeLock("OMTASampler::mSampleTimeLock"),
      mIsInTestMode(false) {
  mController = new OMTAController(aRootLayersId);
}

void OMTASampler::Destroy() {
  StaticMutexAutoLock lock(sWindowIdLock);
  if (mWindowId) {
    MOZ_ASSERT(sWindowIdMap);
    sWindowIdMap->erase(wr::AsUint64(*mWindowId));
  }
}

void OMTASampler::SetWebRenderWindowId(const wr::WrWindowId& aWindowId) {
  StaticMutexAutoLock lock(sWindowIdLock);
  MOZ_ASSERT(!mWindowId);
  mWindowId = Some(aWindowId);
  if (!sWindowIdMap) {
    sWindowIdMap = new std::unordered_map<uint64_t, RefPtr<OMTASampler>>();
    NS_DispatchToMainThread(
        NS_NewRunnableFunction("OMTASampler::ClearOnShutdown",
                               [] { ClearOnShutdown(&sWindowIdMap); }));
  }
  (*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
}

/*static*/
void OMTASampler::SetSamplerThread(const wr::WrWindowId& aWindowId) {
  if (RefPtr<OMTASampler> sampler = GetSampler(aWindowId)) {
    MutexAutoLock lock(sampler->mThreadIdLock);
    sampler->mSamplerThreadId = Some(PlatformThread::CurrentId());
  }
}

/*static*/
void OMTASampler::Sample(const wr::WrWindowId& aWindowId,
                         wr::Transaction* aTransaction) {
  if (RefPtr<OMTASampler> sampler = GetSampler(aWindowId)) {
    wr::TransactionWrapper txn(aTransaction);
    sampler->Sample(txn);
  }
}

void OMTASampler::SetSampleTime(const TimeStamp& aSampleTime) {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());

  const bool hasAnimations = HasAnimations();

  MutexAutoLock lock(mSampleTimeLock);

  // Reset the previous time stamp if we don't already have any running
  // animations to avoid using the time which is far behind for newly
  // started animations.
  mPreviousSampleTime = hasAnimations ? std::move(mSampleTime) : TimeStamp();
  mSampleTime = aSampleTime;
}

void OMTASampler::ResetPreviousSampleTime() {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MutexAutoLock lock(mSampleTimeLock);

  mPreviousSampleTime = TimeStamp();
}

void OMTASampler::Sample(wr::TransactionWrapper& aTxn) {
  MOZ_ASSERT(IsSamplerThread());

  // If we are in test mode, don't sample with the current time stamp, it will
  // skew cached animation values.
  if (mIsInTestMode) {
    return;
  }

  TimeStamp sampleTime;
  TimeStamp previousSampleTime;
  {  // scope lock
    MutexAutoLock lock(mSampleTimeLock);

    // If mSampleTime is null we're in a startup phase where the
    // WebRenderBridgeParent hasn't yet provided us with a sample time.
    // If we're that early there probably aren't any OMTA animations happening
    // anyway, so using Timestamp::Now() should be fine.
    sampleTime = mSampleTime.IsNull() ? TimeStamp::Now() : mSampleTime;
    previousSampleTime = mPreviousSampleTime;
  }

  WrAnimations animations = SampleAnimations(previousSampleTime, sampleTime);

  aTxn.AppendDynamicProperties(animations.mOpacityArrays,
                               animations.mTransformArrays,
                               animations.mColorArrays);
}

WrAnimations OMTASampler::SampleAnimations(const TimeStamp& aPreviousSampleTime,
                                           const TimeStamp& aSampleTime) {
  MOZ_ASSERT(IsSamplerThread());

  MutexAutoLock lock(mStorageLock);

  mAnimStorage->SampleAnimations(mController, aPreviousSampleTime, aSampleTime);

  return mAnimStorage->CollectWebRenderAnimations();
}

OMTAValue OMTASampler::GetOMTAValue(const uint64_t& aId) const {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MutexAutoLock lock(mStorageLock);

  return mAnimStorage->GetOMTAValue(aId);
}

void OMTASampler::SampleForTesting(const Maybe<TimeStamp>& aTestingSampleTime) {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());

  TimeStamp sampleTime;
  TimeStamp previousSampleTime;
  {  // scope lock
    MutexAutoLock timeLock(mSampleTimeLock);
    if (aTestingSampleTime) {
      // If we are on testing refresh mode, use the testing time stamp for both
      // of the previous sample time and the current sample time since unlike
      // normal refresh mode, the testing mode animations on the compositor are
      // synchronously composed, so we don't need to worry about the time gap
      // between the main thread and compositor thread.
      sampleTime = *aTestingSampleTime;
      previousSampleTime = *aTestingSampleTime;
    } else {
      sampleTime = mSampleTime;
      previousSampleTime = mPreviousSampleTime;
    }
  }

  MutexAutoLock storageLock(mStorageLock);
  mAnimStorage->SampleAnimations(mController, previousSampleTime, sampleTime);
}

void OMTASampler::SetAnimations(
    uint64_t aId, const LayersId& aLayersId,
    const nsTArray<layers::Animation>& aAnimations) {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MutexAutoLock lock(mStorageLock);
  MutexAutoLock timeLock(mSampleTimeLock);
  mAnimStorage->SetAnimations(aId, aLayersId, aAnimations, mPreviousSampleTime);
}

bool OMTASampler::HasAnimations() const {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MutexAutoLock lock(mStorageLock);

  return mAnimStorage->HasAnimations();
}

void OMTASampler::ClearActiveAnimations(
    std::unordered_map<uint64_t, wr::WrEpoch>& aActiveAnimations) {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MutexAutoLock lock(mStorageLock);
  for (const auto& id : aActiveAnimations) {
    mAnimStorage->ClearById(id.first);
  }
}

void OMTASampler::RemoveEpochDataPriorTo(
    std::queue<CompositorAnimationIdsForEpoch>& aCompositorAnimationsToDelete,
    std::unordered_map<uint64_t, wr::WrEpoch>& aActiveAnimations,
    const wr::WrEpoch& aRenderedEpoch) {
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
  MutexAutoLock lock(mStorageLock);

  while (!aCompositorAnimationsToDelete.empty()) {
    if (aRenderedEpoch < aCompositorAnimationsToDelete.front().mEpoch) {
      break;
    }
    for (uint64_t id : aCompositorAnimationsToDelete.front().mIds) {
      const auto activeAnim = aActiveAnimations.find(id);
      if (activeAnim == aActiveAnimations.end()) {
        NS_ERROR("Tried to delete invalid animation");
        continue;
      }
      // Check if animation delete request is still valid.
      if (activeAnim->second <= aCompositorAnimationsToDelete.front().mEpoch) {
        mAnimStorage->ClearById(id);
        aActiveAnimations.erase(activeAnim);
      }
    }
    aCompositorAnimationsToDelete.pop();
  }
}

bool OMTASampler::IsSamplerThread() const {
  MutexAutoLock lock(mThreadIdLock);
  return mSamplerThreadId && PlatformThread::CurrentId() == *mSamplerThreadId;
}

/*static*/
already_AddRefed<OMTASampler> OMTASampler::GetSampler(
    const wr::WrWindowId& aWindowId) {
  RefPtr<OMTASampler> sampler;
  StaticMutexAutoLock lock(sWindowIdLock);
  if (sWindowIdMap) {
    auto it = sWindowIdMap->find(wr::AsUint64(aWindowId));
    if (it != sWindowIdMap->end()) {
      sampler = it->second;
    }
  }
  return sampler.forget();
}

}  // namespace layers
}  // namespace mozilla

void omta_register_sampler(mozilla::wr::WrWindowId aWindowId) {
  mozilla::layers::OMTASampler::SetSamplerThread(aWindowId);
}

void omta_sample(mozilla::wr::WrWindowId aWindowId,
                 mozilla::wr::Transaction* aTransaction) {
  mozilla::layers::OMTASampler::Sample(aWindowId, aTransaction);
}

void omta_deregister_sampler(mozilla::wr::WrWindowId aWindowId) {}

Messung V0.5
C=86 H=94 G=89

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.