Unreviewed, rolling out r219610.
[WebKit-https.git] / Source / WebCore / page / linux / ResourceUsageOverlayLinux.cpp
1 /*
2  * Copyright (C) 2017 Igalia S.L.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ResourceUsageOverlay.h"
28
29 #if ENABLE(RESOURCE_USAGE) && OS(LINUX)
30
31 #include "Chrome.h"
32 #include "ChromeClient.h"
33 #include "CommonVM.h"
34 #include "GraphicsContext.h"
35 #include "Page.h"
36 #include "RenderTheme.h"
37 #include "ResourceUsageThread.h"
38 #include <runtime/VM.h>
39
40 namespace WebCore {
41
42 static ResourceUsageData gData;
43
44 static String cpuUsageString(float cpuUsage)
45 {
46     if (cpuUsage < 0)
47         return ASCIILiteral("<unknown>");
48     return String::format("%.1f%%", cpuUsage);
49 }
50
51 static String formatByteNumber(size_t number)
52 {
53     if (number >= 1024 * 1048576)
54         return String::format("%.3f GB", static_cast<double>(number) / (1024 * 1048576));
55     if (number >= 1048576)
56         return String::format("%.2f MB", static_cast<double>(number) / 1048576);
57     if (number >= 1024)
58         return String::format("%.1f kB", static_cast<double>(number) / 1024);
59     return String::format("%lu", number);
60 }
61
62 static String gcTimerString(MonotonicTime timerFireDate, MonotonicTime now)
63 {
64     if (std::isnan(timerFireDate))
65         return ASCIILiteral("[not scheduled]");
66     return String::format("%g", (timerFireDate - now).seconds());
67 }
68
69 static const float gFontSize = 14;
70
71 class ResourceUsageOverlayPainter final : public GraphicsLayerClient {
72 public:
73     ResourceUsageOverlayPainter(ResourceUsageOverlay& overlay)
74         : m_overlay(overlay)
75     {
76         FontCascadeDescription fontDescription;
77         RenderTheme::singleton().systemFont(CSSValueMessageBox, fontDescription);
78         fontDescription.setComputedSize(gFontSize);
79         m_textFont = FontCascade(fontDescription, 0, 0);
80         m_textFont.update(nullptr);
81     }
82
83     ~ResourceUsageOverlayPainter()
84     {
85     }
86
87 private:
88     void paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const FloatRect& clip, GraphicsLayerPaintFlags) override
89     {
90         GraphicsContextStateSaver stateSaver(context);
91         context.fillRect(clip, Color(0.0f, 0.0f, 0.0f, 0.8f));
92         context.setFillColor(Color(0.9f, 0.9f, 0.9f, 1.f));
93
94         FloatPoint position = { 10, 20 };
95         String string =  "CPU: " + cpuUsageString(gData.cpu);
96         context.drawText(m_textFont, TextRun(string), position);
97         position.move(0, gFontSize + 2);
98
99         string = "Memory: " + formatByteNumber(gData.totalDirtySize);
100         context.drawText(m_textFont, TextRun(string), position);
101         position.move(0, gFontSize + 2);
102
103         string = "External: " + formatByteNumber(gData.totalExternalSize);
104         context.drawText(m_textFont, TextRun(string), position);
105         position.move(0, gFontSize + 2);
106
107         string = "GC Heap: " + formatByteNumber(gData.categories[MemoryCategory::GCHeap].dirtySize);
108         context.drawText(m_textFont, TextRun(string), position);
109         position.move(0, gFontSize + 2);
110
111         string = "GC owned: " + formatByteNumber(gData.categories[MemoryCategory::GCOwned].dirtySize);
112         context.drawText(m_textFont, TextRun(string), position);
113         position.move(0, gFontSize + 2);
114
115         MonotonicTime now = MonotonicTime::now();
116         string = "Eden GC: " + gcTimerString(gData.timeOfNextEdenCollection, now);
117         context.drawText(m_textFont, TextRun(string), position);
118         position.move(0, gFontSize + 2);
119
120         string = "Full GC: " + gcTimerString(gData.timeOfNextFullCollection, now);
121         context.drawText(m_textFont, TextRun(string), position);
122         position.move(0, gFontSize + 2);
123     }
124
125     void notifyFlushRequired(const GraphicsLayer*) override
126     {
127         m_overlay.overlay().page()->chrome().client().scheduleCompositingLayerFlush();
128     }
129
130     ResourceUsageOverlay& m_overlay;
131     FontCascade m_textFont;
132 };
133
134 void ResourceUsageOverlay::platformInitialize()
135 {
136     m_overlayPainter = std::make_unique<ResourceUsageOverlayPainter>(*this);
137     m_paintLayer = GraphicsLayer::create(overlay().page()->chrome().client().graphicsLayerFactory(), *m_overlayPainter);
138     m_paintLayer->setAnchorPoint(FloatPoint3D());
139     m_paintLayer->setSize({ normalWidth, normalHeight });
140     m_paintLayer->setBackgroundColor(Color(0.0f, 0.0f, 0.0f, 0.8f));
141     m_paintLayer->setDrawsContent(true);
142     overlay().layer().addChild(m_paintLayer.get());
143
144     ResourceUsageThread::addObserver(this, [this] (const ResourceUsageData& data) {
145         gData = data;
146         m_paintLayer->setNeedsDisplay();
147     });
148 }
149
150 void ResourceUsageOverlay::platformDestroy()
151 {
152     ResourceUsageThread::removeObserver(this);
153     if (!m_paintLayer)
154         return;
155
156     m_paintLayer->removeFromParent();
157     m_paintLayer = nullptr;
158     m_overlayPainter = nullptr;
159 }
160
161 } // namespace WebCore
162
163 #endif // ENABLE(RESOURCE_USAGE) && OS(LINUX)