<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[211244] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/211244">211244</a></dd>
<dt>Author</dt> <dd>dino@apple.com</dd>
<dt>Date</dt> <dd>2017-01-26 17:14:22 -0800 (Thu, 26 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebGL content in Safari sticks to GPU that it was started on, sometimes causing extra battery drain and difficulty interacting with UI
https://bugs.webkit.org/show_bug.cgi?id=167477
&lt;rdar://problem/29956321&gt;

Reviewed by Tim Horton.

We were not implementing the recommended approach to properly handle
GPU switching, causing some contexts to remain on a GPU and slow
down the machine's UI. It also could stop the discrete GPU from
turning off.

Register for CGL's display reconfiguration notification, so that we
can alert any active CGLContexts and cause them to update.

The code change here doesn't lend itself to automated testing because
it is specific to hardware with multiple GPUs, relies on some separate
tools to detect which GPU is active, and an external method of triggering
a GPU switch. It's best tested by the manual workflow in Radar.

* platform/graphics/GraphicsContext3D.h: Add a macOS-specific update
call.
* platform/graphics/mac/GraphicsContext3DMac.mm:
(WebCore::displayWasReconfigured): The callback for display reconfigurations.
(WebCore::addActiveContext): Helper to keep track of active contexts, so we
can register/unregister the callback when necessary.
(WebCore::removeActiveContext):
(WebCore::GraphicsContext3D::create): Use the new helpers.
(WebCore::GraphicsContext3D::~GraphicsContext3D):
(WebCore::GraphicsContext3D::updateCGLContext): Tell the CGLContextRef to update.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsGraphicsContext3Dh">trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacGraphicsContext3DMacmm">trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (211243 => 211244)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-01-27 01:01:30 UTC (rev 211243)
+++ trunk/Source/WebCore/ChangeLog        2017-01-27 01:14:22 UTC (rev 211244)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2017-01-26  Dean Jackson  &lt;dino@apple.com&gt;
+
+        WebGL content in Safari sticks to GPU that it was started on, sometimes causing extra battery drain and difficulty interacting with UI
+        https://bugs.webkit.org/show_bug.cgi?id=167477
+        &lt;rdar://problem/29956321&gt;
+
+        Reviewed by Tim Horton.
+
+        We were not implementing the recommended approach to properly handle
+        GPU switching, causing some contexts to remain on a GPU and slow
+        down the machine's UI. It also could stop the discrete GPU from
+        turning off.
+
+        Register for CGL's display reconfiguration notification, so that we
+        can alert any active CGLContexts and cause them to update.
+
+        The code change here doesn't lend itself to automated testing because
+        it is specific to hardware with multiple GPUs, relies on some separate
+        tools to detect which GPU is active, and an external method of triggering
+        a GPU switch. It's best tested by the manual workflow in Radar.
+
+        * platform/graphics/GraphicsContext3D.h: Add a macOS-specific update
+        call.
+        * platform/graphics/mac/GraphicsContext3DMac.mm:
+        (WebCore::displayWasReconfigured): The callback for display reconfigurations.
+        (WebCore::addActiveContext): Helper to keep track of active contexts, so we
+        can register/unregister the callback when necessary.
+        (WebCore::removeActiveContext):
+        (WebCore::GraphicsContext3D::create): Use the new helpers.
+        (WebCore::GraphicsContext3D::~GraphicsContext3D):
+        (WebCore::GraphicsContext3D::updateCGLContext): Tell the CGLContextRef to update.
+
</ins><span class="cx"> 2017-01-26  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r210328.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsGraphicsContext3Dh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h (211243 => 211244)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h        2017-01-27 01:01:30 UTC (rev 211243)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h        2017-01-27 01:14:22 UTC (rev 211244)
</span><span class="lines">@@ -1137,6 +1137,9 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     void endPaint();
</span><span class="cx"> #endif
</span><ins>+#if PLATFORM(MAC)
+    void updateCGLContext();
+#endif
</ins><span class="cx"> 
</span><span class="cx">     // Support for buffer creation and deletion
</span><span class="cx">     Platform3DObject createBuffer();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacGraphicsContext3DMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm (211243 => 211244)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm        2017-01-27 01:01:30 UTC (rev 211243)
+++ trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm        2017-01-27 01:14:22 UTC (rev 211244)
</span><span class="lines">@@ -68,6 +68,46 @@
</span><span class="cx">     return s_activeContexts;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+static void displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags flags, void*)
+{
+    if (flags &amp; kCGDisplaySetModeFlag) {
+        for (auto* context : activeContexts())
+            context-&gt;updateCGLContext();
+    }
+}
+#endif
+
+static void addActiveContext(GraphicsContext3D* context)
+{
+    ASSERT(context);
+    if (!context)
+        return;
+
+    Vector&lt;GraphicsContext3D*&gt;&amp; contexts = activeContexts();
+
+#if PLATFORM(MAC)
+    if (!contexts.size())
+        CGDisplayRegisterReconfigurationCallback(displayWasReconfigured, nullptr);
+#endif
+
+    ASSERT(!contexts.contains(context));
+    contexts.append(context);
+}
+
+static void removeActiveContext(GraphicsContext3D* context)
+{
+    Vector&lt;GraphicsContext3D*&gt;&amp; contexts = activeContexts();
+
+    ASSERT(contexts.contains(context));
+    contexts.removeFirst(context);
+
+#if PLATFORM(MAC)
+    if (!contexts.size())
+        CGDisplayRemoveReconfigurationCallback(displayWasReconfigured, nullptr);
+#endif
+}
+
</ins><span class="cx"> const int MaxActiveContexts = 16;
</span><span class="cx"> const int GPUStatusCheckThreshold = 5;
</span><span class="cx"> int GraphicsContext3D::GPUCheckCounter = 0;
</span><span class="lines">@@ -224,7 +264,7 @@
</span><span class="cx">     if (!context-&gt;m_contextObj)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    contexts.append(context.get());
</del><ins>+    addActiveContext(context.get());
</ins><span class="cx"> 
</span><span class="cx">     return context;
</span><span class="cx"> }
</span><span class="lines">@@ -437,8 +477,7 @@
</span><span class="cx">         [m_webGLLayer setContext:nullptr];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(activeContexts().contains(this));
-    activeContexts().removeFirst(this);
</del><ins>+    removeActiveContext(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="lines">@@ -517,6 +556,19 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+void GraphicsContext3D::updateCGLContext()
+{
+    if (!m_contextObj)
+        return;
+
+    LOG(WebGL, &quot;Detected a mux switch or display reconfiguration. Update the CGLContext.&quot;);
+
+    makeContextCurrent();
+    CGLUpdateContext(m_contextObj);
+}
+#endif
+
</ins><span class="cx"> bool GraphicsContext3D::isGLES2Compliant() const
</span><span class="cx"> {
</span><span class="cx">     return m_isForWebGL2;
</span></span></pre>
</div>
</div>

</body>
</html>