Bug 823610: Make discarding GL contexts of foreground pages on memory pressure pref-able, and pref off for b2g. r=jgilbert,jlebar
authorChris Jones <jones.chris.g@gmail.com>
Thu, 03 Jan 2013 15:39:25 -0800
changeset 123102 fc3fd7c51000b4d73baa10090dcb25a6846fdfd0
parent 123101 b33bd9f6bd697bdc8d69d3bf19c3e8af4667ad6f
child 123103 e6f18c0f3a24b88435a8b9c23541f235d292bed6
push idunknown
push userunknown
push dateunknown
reviewersjgilbert, jlebar
bugs823610
milestone20.0a1
Bug 823610: Make discarding GL contexts of foreground pages on memory pressure pref-able, and pref off for b2g. r=jgilbert,jlebar
b2g/app/b2g.js
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextValidate.cpp
dom/ipc/ProcessPriorityManager.cpp
dom/ipc/ProcessPriorityManager.h
hal/HalTypes.h
modules/libpref/src/init/all.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -610,8 +610,12 @@ pref("font.size.inflation.disabledInMast
 pref("memory.free_dirty_pages", true);
 
 // UAProfile settings
 pref("wap.UAProf.url", "");
 pref("wap.UAProf.tagname", "x-wap-profile");
 
 // Wait up to this much milliseconds when orientation changed
 pref("layers.orientation.sync.timeout", 1000);
+
+// Don't discard WebGL contexts for foreground apps on memory
+// pressure.
+pref("webgl.can-lose-context-in-foreground", false);
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -40,35 +40,40 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/ipc/ProcessPriorityManager.h"
 
 #include "Layers.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::dom;
+using namespace mozilla::dom::ipc;
 using namespace mozilla::layers;
 
 NS_IMETHODIMP
 WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
                                      const char* aTopic,
                                      const PRUnichar* aSomeData)
 {
     if (strcmp(aTopic, "memory-pressure"))
         return NS_OK;
 
     bool wantToLoseContext = true;
 
-    if (!nsCRT::strcmp(aSomeData, NS_LITERAL_STRING("heap-minimize").get()))
+    if (!mContext->mCanLoseContextInForeground && CurrentProcessIsForeground())
+        wantToLoseContext = false;
+    else if (!nsCRT::strcmp(aSomeData,
+                            NS_LITERAL_STRING("heap-minimize").get()))
         wantToLoseContext = mContext->mLoseContextOnHeapMinimize;
 
     if (wantToLoseContext)
         mContext->ForceLoseContext();
 
     return NS_OK;
 }
 
@@ -174,16 +179,17 @@ WebGLContext::WebGLContext()
 
     mAllowRestore = true;
     mContextLossTimerRunning = false;
     mDrawSinceContextLossTimerSet = false;
     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     mContextStatus = ContextStable;
     mContextLostErrorSet = false;
     mLoseContextOnHeapMinimize = false;
+    mCanLoseContextInForeground = true;
 
     mAlreadyGeneratedWarnings = 0;
     mAlreadyWarnedAboutFakeVertexAttrib0 = false;
 
     mLastUseIndex = 0;
 
     mMinInUseAttribArrayLengthCached = false;
     mMinInUseAttribArrayLength = 0;
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -838,16 +838,17 @@ protected:
     bool mInvalidated;
     bool mResetLayer;
     bool mOptionsFrozen;
     bool mMinCapability;
     bool mDisableExtensions;
     bool mHasRobustness;
     bool mIsMesa;
     bool mLoseContextOnHeapMinimize;
+    bool mCanLoseContextInForeground;
 
     template<typename WebGLObjectType>
     void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
 
     WebGLuint mActiveTexture;
     WebGLenum mWebGLError;
 
     // whether shader validation is supported
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -853,16 +853,17 @@ WebGLContext::InitAndValidateGL()
     if (error != LOCAL_GL_NO_ERROR) {
         GenerateWarning("GL error 0x%x occurred during OpenGL context initialization, before WebGL initialization!", error);
         return false;
     }
 
     mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
     mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
     mLoseContextOnHeapMinimize = Preferences::GetBool("webgl.lose-context-on-heap-minimize", false);
+    mCanLoseContextInForeground = Preferences::GetBool("webgl.can-lose-context-in-foreground", true);
 
     mActiveTexture = 0;
     mWebGLError = LOCAL_GL_NO_ERROR;
 
     mAttribBuffers.Clear();
 
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* 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/ClearOnShutdown.h"
 #include "mozilla/dom/ipc/ProcessPriorityManager.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/Hal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/TimeStamp.h"
@@ -21,32 +22,35 @@
 #include "nsIObserverService.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMDocument.h"
 #include "nsPIDOMWindow.h"
+#include "StaticPtr.h"
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
 #include <unistd.h>
 #endif
 
 using namespace mozilla::hal;
 
 namespace mozilla {
 namespace dom {
 namespace ipc {
 
 namespace {
 static bool sInitialized = false;
+class ProcessPriorityManager;
+static StaticRefPtr<ProcessPriorityManager> sManager;
 
 // Some header defines a LOG macro, but we don't want it here.
 #ifdef LOG
 #undef LOG
 #endif
 
 // Enable logging by setting
 //
@@ -122,16 +126,18 @@ class ProcessPriorityManager MOZ_FINAL
 public:
   ProcessPriorityManager();
   void Init();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMEVENTLISTENER
 
+  ProcessPriority GetPriority() const { return mProcessPriority; }
+
 private:
   void SetPriority(ProcessPriority aPriority);
   void OnContentDocumentGlobalCreated(nsISupports* aOuterWindow);
   void OnInnerWindowDestroyed();
   void OnGracePeriodTimerFired();
   void RecomputeNumVisibleWindows();
 
   // mProcessPriority tracks the priority we've given this process in hal,
@@ -384,16 +390,22 @@ InitProcessPriorityManager()
   // ProcessPriorityManager (we never want to mark the master process as
   // backgrounded).
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     LOG("This is the master process.");
     hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER);
     return;
   }
 
-  // This object is held alive by the observer service.
-  nsRefPtr<ProcessPriorityManager> mgr = new ProcessPriorityManager();
-  mgr->Init();
+  sManager = new ProcessPriorityManager();
+  sManager->Init();
+  ClearOnShutdown(&sManager);
+}
+
+bool
+CurrentProcessIsForeground()
+{
+  return sManager->GetPriority() >= PROCESS_PRIORITY_FOREGROUND;
 }
 
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ProcessPriorityManager.h
+++ b/dom/ipc/ProcessPriorityManager.h
@@ -21,13 +21,20 @@ namespace ipc {
  *
  * Hal may adjust this process's operating system priority (e.g. niceness, on
  * *nix) according to these notificaitons.
  *
  * This function call does nothing if the pref for OOP tabs is not set.
  */
 void InitProcessPriorityManager();
 
+/**
+ * True iff the current process has foreground or higher priority as
+ * computed by DOM visibility.  The returned answer may not match the
+ * actual OS process priority, for short intervals.
+ */
+bool CurrentProcessIsForeground();
+
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -65,16 +65,19 @@ enum SwitchState {
   NUM_SWITCH_STATE
 };
 
 typedef Observer<SwitchEvent> SwitchObserver;
 
 enum ProcessPriority {
   PROCESS_PRIORITY_BACKGROUND,
   PROCESS_PRIORITY_BACKGROUND_HOMESCREEN,
+  // Any priority greater than or equal to FOREGROUND is considered
+  // "foreground" for the purposes of priority testing, for example
+  // CurrentProcessIsForeground().
   PROCESS_PRIORITY_FOREGROUND,
   PROCESS_PRIORITY_MASTER,
   NUM_PROCESS_PRIORITY
 };
 
 /**
  * Used by ModifyWakeLock
  */
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3701,16 +3701,17 @@ pref("webgl.prefer-native-gl", false);
 pref("webgl.min_capability_mode", false);
 pref("webgl.disable-extensions", false);
 pref("webgl.msaa-level", 2);
 pref("webgl.msaa-force", false);
 pref("webgl.prefer-16bpp", false);
 pref("webgl.default-no-alpha", false);
 pref("webgl.force-layers-readback", false);
 pref("webgl.lose-context-on-heap-minimize", false);
+pref("webgl.can-lose-context-in-foreground", true);
 
 // Stagefright prefs
 pref("stagefright.force-enabled", false);
 pref("stagefright.disabled", false);
 
 #ifdef XP_WIN
 // The default TCP send window on Windows is too small, and autotuning only occurs on receive
 pref("network.tcp.sendbuffer", 131072);