Reduce copying of FontCascadeDescription objects by moving them around
[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 <JavaScriptCore/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(WTFMove(fontDescription), 0, 0);
80         m_textFont.update(nullptr);
81     }
82
83     ~ResourceUsageOverlayPainter() = default;
84
85 private:
86     void paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const FloatRect& clip, GraphicsLayerPaintBehavior) override
87     {
88         GraphicsContextStateSaver stateSaver(context);
89         context.fillRect(clip, Color(0.0f, 0.0f, 0.0f, 0.8f));
90         context.setFillColor(Color(0.9f, 0.9f, 0.9f, 1.f));
91
92         FloatPoint position = { 10, 20 };
93         String string =  "CPU: " + cpuUsageString(gData.cpu);
94         context.drawText(m_textFont, TextRun(string), position);
95         position.move(0, gFontSize + 2);
96
97         string = "Memory: " + formatByteNumber(gData.totalDirtySize);
98         context.drawText(m_textFont, TextRun(string), position);
99         position.move(0, gFontSize + 2);
100
101         string = "External: " + formatByteNumber(gData.totalExternalSize);
102         context.drawText(m_textFont, TextRun(string), position);
103         position.move(0, gFontSize + 2);
104
105         string = "GC Heap: " + formatByteNumber(gData.categories[MemoryCategory::GCHeap].dirtySize);
106         context.drawText(m_textFont, TextRun(string), position);
107         position.move(0, gFontSize + 2);
108
109         string = "GC owned: " + formatByteNumber(gData.categories[MemoryCategory::GCOwned].dirtySize);
110         context.drawText(m_textFont, TextRun(string), position);
111         position.move(0, gFontSize + 2);
112
113         MonotonicTime now = MonotonicTime::now();
114         string = "Eden GC: " + gcTimerString(gData.timeOfNextEdenCollection, now);
115         context.drawText(m_textFont, TextRun(string), position);
116         position.move(0, gFontSize + 2);
117
118         string = "Full GC: " + gcTimerString(gData.timeOfNextFullCollection, now);
119         context.drawText(m_textFont, TextRun(string), position);
120         position.move(0, gFontSize + 2);
121     }
122
123     void notifyFlushRequired(const GraphicsLayer*) override
124     {
125         m_overlay.overlay().page()->chrome().client().scheduleCompositingLayerFlush();
126     }
127
128     ResourceUsageOverlay& m_overlay;
129     FontCascade m_textFont;
130 };
131
132 void ResourceUsageOverlay::platformInitialize()
133 {
134     m_overlayPainter = std::make_unique<ResourceUsageOverlayPainter>(*this);
135     m_paintLayer = GraphicsLayer::create(overlay().page()->chrome().client().graphicsLayerFactory(), *m_overlayPainter);
136     m_paintLayer->setAnchorPoint(FloatPoint3D());
137     m_paintLayer->setSize({ normalWidth, normalHeight });
138     m_paintLayer->setBackgroundColor(Color(0.0f, 0.0f, 0.0f, 0.8f));
139     m_paintLayer->setDrawsContent(true);
140     overlay().layer().addChild(m_paintLayer.get());
141
142     ResourceUsageThread::addObserver(this, [this] (const ResourceUsageData& data) {
143         gData = data;
144         m_paintLayer->setNeedsDisplay();
145     });
146 }
147
148 void ResourceUsageOverlay::platformDestroy()
149 {
150     ResourceUsageThread::removeObserver(this);
151     if (!m_paintLayer)
152         return;
153
154     m_paintLayer->removeFromParent();
155     m_paintLayer = nullptr;
156     m_overlayPainter = nullptr;
157 }
158
159 } // namespace WebCore
160
161 #endif // ENABLE(RESOURCE_USAGE) && OS(LINUX)