Line data Source code
1 : /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set sts=2 ts=8 sw=2 tw=99 et: */
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 "gfxVars.h"
8 : #include "gfxVarReceiver.h"
9 : #include "mozilla/dom/ContentChild.h"
10 :
11 : namespace mozilla {
12 : namespace gfx {
13 :
14 3 : StaticAutoPtr<gfxVars> gfxVars::sInstance;
15 3 : StaticAutoPtr<nsTArray<gfxVars::VarBase*>> gfxVars::sVarList;
16 :
17 3 : StaticAutoPtr<nsTArray<GfxVarUpdate>> gGfxVarInitUpdates;
18 :
19 : void
20 2 : gfxVars::SetValuesForInitialize(const nsTArray<GfxVarUpdate>& aInitUpdates)
21 : {
22 : // This should only be called once
23 2 : MOZ_RELEASE_ASSERT(!gGfxVarInitUpdates);
24 :
25 : // We expect aInitUpdates to be provided before any other gfxVars operation,
26 : // and for sInstance to be null here, but handle the alternative.
27 2 : if (sInstance) {
28 : // Apply the updates, the object has been created already
29 0 : for (const auto& varUpdate : aInitUpdates) {
30 0 : ApplyUpdate(varUpdate);
31 : }
32 : } else {
33 : // Save the values for Initialize call
34 2 : gGfxVarInitUpdates = new nsTArray<GfxVarUpdate>(aInitUpdates);
35 : }
36 2 : }
37 :
38 : void
39 3 : gfxVars::Initialize()
40 : {
41 3 : if (sInstance) {
42 0 : MOZ_RELEASE_ASSERT(!gGfxVarInitUpdates, "Initial updates should not be present after any gfxVars operation");
43 0 : return;
44 : }
45 :
46 : // sVarList must be initialized first since it's used in the constructor for
47 : // sInstance.
48 3 : sVarList = new nsTArray<gfxVars::VarBase*>();
49 3 : sInstance = new gfxVars;
50 :
51 : // Note the GPU process is not handled here - it cannot send sync
52 : // messages, so instead the initial data is pushed down.
53 3 : if (XRE_IsContentProcess()) {
54 2 : MOZ_ASSERT(gGfxVarInitUpdates, "Initial updates should be provided in content process");
55 2 : if (!gGfxVarInitUpdates) {
56 : // No provided initial updates, sync-request them from parent.
57 0 : InfallibleTArray<GfxVarUpdate> initUpdates;
58 0 : dom::ContentChild::GetSingleton()->SendGetGfxVars(&initUpdates);
59 0 : gGfxVarInitUpdates = new nsTArray<GfxVarUpdate>(Move(initUpdates));
60 : }
61 16 : for (const auto& varUpdate : *gGfxVarInitUpdates) {
62 14 : ApplyUpdate(varUpdate);
63 : }
64 2 : gGfxVarInitUpdates = nullptr;
65 : }
66 : }
67 :
68 3 : gfxVars::gfxVars()
69 : {
70 3 : }
71 :
72 : void
73 0 : gfxVars::Shutdown()
74 : {
75 0 : sInstance = nullptr;
76 0 : sVarList = nullptr;
77 0 : gGfxVarInitUpdates = nullptr;
78 0 : }
79 :
80 : /* static */ void
81 14 : gfxVars::ApplyUpdate(const GfxVarUpdate& aUpdate)
82 : {
83 : // Only subprocesses receive updates and apply them locally.
84 14 : MOZ_ASSERT(!XRE_IsParentProcess());
85 14 : MOZ_DIAGNOSTIC_ASSERT(sVarList || gGfxVarInitUpdates);
86 14 : if (sVarList) {
87 14 : sVarList->ElementAt(aUpdate.index())->SetValue(aUpdate.value());
88 0 : } else if (gGfxVarInitUpdates) {
89 : // Too early, we haven't been initialized, so just add to
90 : // the array waiting for the initialization...
91 0 : gGfxVarInitUpdates->AppendElement(aUpdate);
92 : }
93 14 : }
94 :
95 : /* static */ void
96 2 : gfxVars::AddReceiver(gfxVarReceiver* aReceiver)
97 : {
98 2 : MOZ_ASSERT(NS_IsMainThread());
99 :
100 : // Don't double-add receivers, in case a broken content process sends two
101 : // init messages.
102 2 : if (!sInstance->mReceivers.Contains(aReceiver)) {
103 2 : sInstance->mReceivers.AppendElement(aReceiver);
104 : }
105 2 : }
106 :
107 : /* static */ void
108 0 : gfxVars::RemoveReceiver(gfxVarReceiver* aReceiver)
109 : {
110 0 : MOZ_ASSERT(NS_IsMainThread());
111 :
112 0 : if (sInstance) {
113 0 : sInstance->mReceivers.RemoveElement(aReceiver);
114 : }
115 0 : }
116 :
117 : /* static */ nsTArray<GfxVarUpdate>
118 2 : gfxVars::FetchNonDefaultVars()
119 : {
120 2 : MOZ_ASSERT(NS_IsMainThread());
121 2 : MOZ_ASSERT(sVarList);
122 :
123 2 : nsTArray<GfxVarUpdate> updates;
124 34 : for (size_t i = 0; i < sVarList->Length(); i++) {
125 32 : VarBase* var = sVarList->ElementAt(i);
126 32 : if (var->HasDefaultValue()) {
127 18 : continue;
128 : }
129 :
130 28 : GfxVarValue value;
131 14 : var->GetValue(&value);
132 :
133 14 : updates.AppendElement(GfxVarUpdate(i, value));
134 : }
135 :
136 2 : return updates;
137 : }
138 :
139 48 : gfxVars::VarBase::VarBase()
140 : {
141 48 : mIndex = gfxVars::sVarList->Length();
142 48 : gfxVars::sVarList->AppendElement(this);
143 48 : }
144 :
145 : void
146 7 : gfxVars::NotifyReceivers(VarBase* aVar)
147 : {
148 7 : MOZ_ASSERT(NS_IsMainThread());
149 :
150 14 : GfxVarValue value;
151 7 : aVar->GetValue(&value);
152 :
153 14 : GfxVarUpdate update(aVar->Index(), value);
154 7 : for (auto& receiver : mReceivers) {
155 0 : receiver->OnVarChanged(update);
156 : }
157 7 : }
158 :
159 : } // namespace gfx
160 9 : } // namespace mozilla
|