1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/layers/TextureSourceProvider.h"
8 #include "mozilla/layers/TextureHost.h"
9 #include "mozilla/layers/PTextureParent.h"
10 #ifdef XP_DARWIN
11 #  include "mozilla/layers/TextureSync.h"
12 #endif
13 
14 namespace mozilla {
15 namespace layers {
16 
~TextureSourceProvider()17 TextureSourceProvider::~TextureSourceProvider() { ReadUnlockTextures(); }
18 
ReadUnlockTextures()19 void TextureSourceProvider::ReadUnlockTextures() {
20 #ifdef XP_DARWIN
21   nsClassHashtable<nsUint32HashKey, nsTArray<uint64_t>>
22       texturesIdsToUnlockByPid;
23   for (auto& texture : mUnlockAfterComposition) {
24     auto bufferTexture = texture->AsBufferTextureHost();
25     if (bufferTexture && bufferTexture->IsDirectMap()) {
26       texture->ReadUnlock();
27       auto actor = texture->GetIPDLActor();
28       if (actor) {
29         base::ProcessId pid = actor->OtherPid();
30         nsTArray<uint64_t>* textureIds =
31             texturesIdsToUnlockByPid.LookupOrAdd(pid);
32         textureIds->AppendElement(TextureHost::GetTextureSerial(actor));
33       }
34     } else {
35       texture->ReadUnlock();
36     }
37   }
38   for (auto it = texturesIdsToUnlockByPid.ConstIter(); !it.Done(); it.Next()) {
39     TextureSync::SetTexturesUnlocked(it.Key(), *it.UserData());
40   }
41 #else
42   for (auto& texture : mUnlockAfterComposition) {
43     texture->ReadUnlock();
44   }
45 #endif
46   mUnlockAfterComposition.Clear();
47 }
48 
UnlockAfterComposition(TextureHost * aTexture)49 void TextureSourceProvider::UnlockAfterComposition(TextureHost* aTexture) {
50   mUnlockAfterComposition.AppendElement(aTexture);
51 }
52 
NotifyNotUsedAfterComposition(TextureHost * aTextureHost)53 bool TextureSourceProvider::NotifyNotUsedAfterComposition(
54     TextureHost* aTextureHost) {
55   mNotifyNotUsedAfterComposition.AppendElement(aTextureHost);
56 
57   // If Compositor holds many TextureHosts without compositing,
58   // the TextureHosts should be flushed to reduce memory consumption.
59   const int thresholdCount = 5;
60   const double thresholdSec = 2.0f;
61   if (mNotifyNotUsedAfterComposition.Length() > thresholdCount) {
62     TimeStamp lastCompositionEndTime = GetLastCompositionEndTime();
63     TimeDuration duration = lastCompositionEndTime
64                                 ? TimeStamp::Now() - lastCompositionEndTime
65                                 : TimeDuration();
66     // Check if we could flush
67     if (duration.ToSeconds() > thresholdSec) {
68       FlushPendingNotifyNotUsed();
69     }
70   }
71   return true;
72 }
73 
FlushPendingNotifyNotUsed()74 void TextureSourceProvider::FlushPendingNotifyNotUsed() {
75   for (auto& textureHost : mNotifyNotUsedAfterComposition) {
76     textureHost->CallNotifyNotUsed();
77   }
78   mNotifyNotUsedAfterComposition.Clear();
79 }
80 
Destroy()81 void TextureSourceProvider::Destroy() {
82   ReadUnlockTextures();
83   FlushPendingNotifyNotUsed();
84 }
85 
86 }  // namespace layers
87 }  // namespace mozilla
88