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 126633 fc3fd7c51000b4d73baa10090dcb25a6846fdfd0
parent 126632 b33bd9f6bd697bdc8d69d3bf19c3e8af4667ad6f
child 126634 e6f18c0f3a24b88435a8b9c23541f235d292bed6
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, jlebar
bugs823610
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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);