1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "gfxPrefs.h"
7
8 #include "MainThreadUtils.h"
9 #include "nsXULAppAPI.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/Unused.h"
12 #include "mozilla/gfx/Logging.h"
13 #include "mozilla/gfx/GPUChild.h"
14 #include "mozilla/gfx/GPUProcessManager.h"
15
16 using namespace mozilla;
17
18 nsTArray<gfxPrefs::Pref*>* gfxPrefs::sGfxPrefList = nullptr;
19 gfxPrefs* gfxPrefs::sInstance = nullptr;
20 bool gfxPrefs::sInstanceHasBeenDestroyed = false;
21
22 void
DestroySingleton()23 gfxPrefs::DestroySingleton()
24 {
25 if (sInstance) {
26 delete sInstance;
27 sInstance = nullptr;
28 sInstanceHasBeenDestroyed = true;
29 }
30 MOZ_ASSERT(!SingletonExists());
31 }
32
33 bool
SingletonExists()34 gfxPrefs::SingletonExists()
35 {
36 return sInstance != nullptr;
37 }
38
gfxPrefs()39 gfxPrefs::gfxPrefs()
40 {
41 // UI, content, and plugin processes use XPCOM and should have prefs
42 // ready by the time we initialize gfxPrefs.
43 MOZ_ASSERT_IF(XRE_IsContentProcess() ||
44 XRE_IsParentProcess() ||
45 XRE_GetProcessType() == GeckoProcessType_Plugin,
46 Preferences::IsServiceAvailable());
47
48 gfxPrefs::AssertMainThread();
49 }
50
51 void
Init()52 gfxPrefs::Init()
53 {
54 // Set up Moz2D prefs.
55 mPrefGfxLoggingLevel.SetChangeCallback([]() -> void {
56 mozilla::gfx::LoggingPrefs::sGfxLogLevel = GetSingleton().mPrefGfxLoggingLevel.GetLiveValue();
57 });
58 }
59
~gfxPrefs()60 gfxPrefs::~gfxPrefs()
61 {
62 gfxPrefs::AssertMainThread();
63 mPrefGfxLoggingLevel.SetChangeCallback(nullptr);
64 delete sGfxPrefList;
65 sGfxPrefList = nullptr;
66 }
67
AssertMainThread()68 void gfxPrefs::AssertMainThread()
69 {
70 MOZ_ASSERT(NS_IsMainThread(), "this code must be run on the main thread");
71 }
72
73 void
OnChange()74 gfxPrefs::Pref::OnChange()
75 {
76 if (auto gpm = gfx::GPUProcessManager::Get()) {
77 if (gfx::GPUChild* gpu = gpm->GetGPUChild()) {
78 GfxPrefValue value;
79 GetLiveValue(&value);
80 Unused << gpu->SendUpdatePref(gfx::GfxPrefSetting(mIndex, value));
81 }
82 }
83 FireChangeCallback();
84 }
85
86 void
FireChangeCallback()87 gfxPrefs::Pref::FireChangeCallback()
88 {
89 if (mChangeCallback) {
90 mChangeCallback();
91 }
92 }
93
94 void
SetChangeCallback(ChangeCallback aCallback)95 gfxPrefs::Pref::SetChangeCallback(ChangeCallback aCallback)
96 {
97 mChangeCallback = aCallback;
98
99 if (!IsParentProcess() && IsPrefsServiceAvailable()) {
100 // If we're in the parent process, we watch prefs by default so we can
101 // send changes over to the GPU process. Otherwise, we need to add or
102 // remove a watch for the pref now.
103 if (aCallback) {
104 WatchChanges(Name(), this);
105 } else {
106 UnwatchChanges(Name(), this);
107 }
108 }
109
110 // Fire the callback once to make initialization easier for the caller.
111 FireChangeCallback();
112 }
113
114 // On lightweight processes such as for GMP and GPU, XPCOM is not initialized,
115 // and therefore we don't have access to Preferences. When XPCOM is not
116 // available we rely on manual synchronization of gfxPrefs values over IPC.
117 /* static */ bool
IsPrefsServiceAvailable()118 gfxPrefs::IsPrefsServiceAvailable()
119 {
120 return Preferences::IsServiceAvailable();
121 }
122
123 /* static */ bool
IsParentProcess()124 gfxPrefs::IsParentProcess()
125 {
126 return XRE_IsParentProcess();
127 }
128
PrefAddVarCache(bool * aVariable,const char * aPref,bool aDefault)129 void gfxPrefs::PrefAddVarCache(bool* aVariable,
130 const char* aPref,
131 bool aDefault)
132 {
133 MOZ_ASSERT(IsPrefsServiceAvailable());
134 Preferences::AddBoolVarCache(aVariable, aPref, aDefault);
135 }
136
PrefAddVarCache(int32_t * aVariable,const char * aPref,int32_t aDefault)137 void gfxPrefs::PrefAddVarCache(int32_t* aVariable,
138 const char* aPref,
139 int32_t aDefault)
140 {
141 MOZ_ASSERT(IsPrefsServiceAvailable());
142 Preferences::AddIntVarCache(aVariable, aPref, aDefault);
143 }
144
PrefAddVarCache(uint32_t * aVariable,const char * aPref,uint32_t aDefault)145 void gfxPrefs::PrefAddVarCache(uint32_t* aVariable,
146 const char* aPref,
147 uint32_t aDefault)
148 {
149 MOZ_ASSERT(IsPrefsServiceAvailable());
150 Preferences::AddUintVarCache(aVariable, aPref, aDefault);
151 }
152
PrefAddVarCache(float * aVariable,const char * aPref,float aDefault)153 void gfxPrefs::PrefAddVarCache(float* aVariable,
154 const char* aPref,
155 float aDefault)
156 {
157 MOZ_ASSERT(IsPrefsServiceAvailable());
158 Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
159 }
160
PrefGet(const char * aPref,bool aDefault)161 bool gfxPrefs::PrefGet(const char* aPref, bool aDefault)
162 {
163 MOZ_ASSERT(IsPrefsServiceAvailable());
164 return Preferences::GetBool(aPref, aDefault);
165 }
166
PrefGet(const char * aPref,int32_t aDefault)167 int32_t gfxPrefs::PrefGet(const char* aPref, int32_t aDefault)
168 {
169 MOZ_ASSERT(IsPrefsServiceAvailable());
170 return Preferences::GetInt(aPref, aDefault);
171 }
172
PrefGet(const char * aPref,uint32_t aDefault)173 uint32_t gfxPrefs::PrefGet(const char* aPref, uint32_t aDefault)
174 {
175 MOZ_ASSERT(IsPrefsServiceAvailable());
176 return Preferences::GetUint(aPref, aDefault);
177 }
178
PrefGet(const char * aPref,float aDefault)179 float gfxPrefs::PrefGet(const char* aPref, float aDefault)
180 {
181 MOZ_ASSERT(IsPrefsServiceAvailable());
182 return Preferences::GetFloat(aPref, aDefault);
183 }
184
PrefSet(const char * aPref,bool aValue)185 void gfxPrefs::PrefSet(const char* aPref, bool aValue)
186 {
187 MOZ_ASSERT(IsPrefsServiceAvailable());
188 Preferences::SetBool(aPref, aValue);
189 }
190
PrefSet(const char * aPref,int32_t aValue)191 void gfxPrefs::PrefSet(const char* aPref, int32_t aValue)
192 {
193 MOZ_ASSERT(IsPrefsServiceAvailable());
194 Preferences::SetInt(aPref, aValue);
195 }
196
PrefSet(const char * aPref,uint32_t aValue)197 void gfxPrefs::PrefSet(const char* aPref, uint32_t aValue)
198 {
199 MOZ_ASSERT(IsPrefsServiceAvailable());
200 Preferences::SetUint(aPref, aValue);
201 }
202
PrefSet(const char * aPref,float aValue)203 void gfxPrefs::PrefSet(const char* aPref, float aValue)
204 {
205 MOZ_ASSERT(IsPrefsServiceAvailable());
206 Preferences::SetFloat(aPref, aValue);
207 }
208
209 static void
OnGfxPrefChanged(const char * aPrefname,void * aClosure)210 OnGfxPrefChanged(const char* aPrefname, void* aClosure)
211 {
212 reinterpret_cast<gfxPrefs::Pref*>(aClosure)->OnChange();
213 }
214
WatchChanges(const char * aPrefname,Pref * aPref)215 void gfxPrefs::WatchChanges(const char* aPrefname, Pref* aPref)
216 {
217 MOZ_ASSERT(IsPrefsServiceAvailable());
218 Preferences::RegisterCallback(OnGfxPrefChanged, aPrefname, aPref, Preferences::ExactMatch);
219 }
220
UnwatchChanges(const char * aPrefname,Pref * aPref)221 void gfxPrefs::UnwatchChanges(const char* aPrefname, Pref* aPref)
222 {
223 // The Preferences service can go offline before gfxPrefs is destroyed.
224 if (IsPrefsServiceAvailable()) {
225 Preferences::UnregisterCallback(OnGfxPrefChanged, aPrefname, aPref, Preferences::ExactMatch);
226 }
227 }
228
CopyPrefValue(const bool * aValue,GfxPrefValue * aOutValue)229 void gfxPrefs::CopyPrefValue(const bool* aValue, GfxPrefValue* aOutValue)
230 {
231 *aOutValue = *aValue;
232 }
233
CopyPrefValue(const int32_t * aValue,GfxPrefValue * aOutValue)234 void gfxPrefs::CopyPrefValue(const int32_t* aValue, GfxPrefValue* aOutValue)
235 {
236 *aOutValue = *aValue;
237 }
238
CopyPrefValue(const uint32_t * aValue,GfxPrefValue * aOutValue)239 void gfxPrefs::CopyPrefValue(const uint32_t* aValue, GfxPrefValue* aOutValue)
240 {
241 *aOutValue = *aValue;
242 }
243
CopyPrefValue(const float * aValue,GfxPrefValue * aOutValue)244 void gfxPrefs::CopyPrefValue(const float* aValue, GfxPrefValue* aOutValue)
245 {
246 *aOutValue = *aValue;
247 }
248
CopyPrefValue(const GfxPrefValue * aValue,bool * aOutValue)249 void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, bool* aOutValue)
250 {
251 *aOutValue = aValue->get_bool();
252 }
253
CopyPrefValue(const GfxPrefValue * aValue,int32_t * aOutValue)254 void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, int32_t* aOutValue)
255 {
256 *aOutValue = aValue->get_int32_t();
257 }
258
CopyPrefValue(const GfxPrefValue * aValue,uint32_t * aOutValue)259 void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, uint32_t* aOutValue)
260 {
261 *aOutValue = aValue->get_uint32_t();
262 }
263
CopyPrefValue(const GfxPrefValue * aValue,float * aOutValue)264 void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, float* aOutValue)
265 {
266 *aOutValue = aValue->get_float();
267 }
268