summaryrefslogtreecommitdiffstats
path: root/gfx/layers/TextureSourceProvider.cpp
blob: de3505a783e85cdbd7378c910eec99356b963504 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/* -*- 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/TextureSourceProvider.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/PTextureParent.h"
#ifdef XP_DARWIN
#  include "mozilla/layers/TextureSync.h"
#  include "nsClassHashtable.h"
#endif

namespace mozilla {
namespace layers {

TextureSourceProvider::~TextureSourceProvider() { ReadUnlockTextures(); }

void TextureSourceProvider::ReadUnlockTextures() {
#ifdef XP_DARWIN
  nsClassHashtable<nsUint32HashKey, nsTArray<uint64_t>>
      texturesIdsToUnlockByPid;
  for (auto& texture : mUnlockAfterComposition) {
    auto bufferTexture = texture->AsBufferTextureHost();
    if (bufferTexture && bufferTexture->IsDirectMap()) {
      texture->ReadUnlock();
      auto actor = texture->GetIPDLActor();
      if (actor) {
        base::ProcessId pid = actor->OtherPid();
        nsTArray<uint64_t>* textureIds =
            texturesIdsToUnlockByPid.LookupOrAdd(pid);
        textureIds->AppendElement(TextureHost::GetTextureSerial(actor));
      }
    } else {
      texture->ReadUnlock();
    }
  }
  for (auto it = texturesIdsToUnlockByPid.ConstIter(); !it.Done(); it.Next()) {
    TextureSync::SetTexturesUnlocked(it.Key(), *it.UserData());
  }
#else
  for (auto& texture : mUnlockAfterComposition) {
    texture->ReadUnlock();
  }
#endif
  mUnlockAfterComposition.Clear();
}

void TextureSourceProvider::UnlockAfterComposition(TextureHost* aTexture) {
  mUnlockAfterComposition.AppendElement(aTexture);
}

bool TextureSourceProvider::NotifyNotUsedAfterComposition(
    TextureHost* aTextureHost) {
  mNotifyNotUsedAfterComposition.AppendElement(aTextureHost);

  // If Compositor holds many TextureHosts without compositing,
  // the TextureHosts should be flushed to reduce memory consumption.
  const int thresholdCount = 5;
  const double thresholdSec = 2.0f;
  if (mNotifyNotUsedAfterComposition.Length() > thresholdCount) {
    TimeStamp lastCompositionEndTime = GetLastCompositionEndTime();
    TimeDuration duration = lastCompositionEndTime
                                ? TimeStamp::Now() - lastCompositionEndTime
                                : TimeDuration();
    // Check if we could flush
    if (duration.ToSeconds() > thresholdSec) {
      FlushPendingNotifyNotUsed();
    }
  }
  return true;
}

void TextureSourceProvider::FlushPendingNotifyNotUsed() {
  for (auto& textureHost : mNotifyNotUsedAfterComposition) {
    textureHost->CallNotifyNotUsed();
  }
  mNotifyNotUsedAfterComposition.Clear();
}

void TextureSourceProvider::Destroy() {
  ReadUnlockTextures();
  FlushPendingNotifyNotUsed();
}

}  // namespace layers
}  // namespace mozilla