1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // OverlayWidgets.cpp:
7 // Implements functions that interpret widget data. Data formats and limits correspond to the
8 // Vulkan implementation (as the only implementation). They are generic enough so other backends
9 // could respect them too, if they implement the overlay.
10 //
11
12 #include "libANGLE/Overlay.h"
13 #include "libANGLE/Overlay_font_autogen.h"
14
15 #include <functional>
16
17 namespace gl
18 {
19 namespace
20 {
21 // Internally, every widget is either Text or Graph.
22 enum class WidgetInternalType
23 {
24 Text,
25 Graph,
26
27 InvalidEnum,
28 EnumCount = InvalidEnum,
29 };
30
31 // A map that says how the API-facing widget types map to internal types.
32 constexpr angle::PackedEnumMap<WidgetType, WidgetInternalType> kWidgetTypeToInternalMap = {
33 {WidgetType::Count, WidgetInternalType::Text},
34 {WidgetType::Text, WidgetInternalType::Text},
35 {WidgetType::PerSecond, WidgetInternalType::Text},
36 {WidgetType::RunningGraph, WidgetInternalType::Graph},
37 {WidgetType::RunningHistogram, WidgetInternalType::Graph},
38 };
39
40 // Structures and limits matching uniform buffers in vulkan/shaders/src/OverlayDraw.comp. The size
41 // of text and graph widgets is chosen such that they could fit in uniform buffers with minimum
42 // required Vulkan size.
43 constexpr size_t kMaxRenderableTextWidgets = 32;
44 constexpr size_t kMaxRenderableGraphWidgets = 32;
45 constexpr size_t kMaxTextLength = 256;
46 constexpr size_t kMaxGraphDataSize = 256;
47
48 constexpr angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeMaxWidgets = {
49 {WidgetInternalType::Text, kMaxRenderableTextWidgets},
50 {WidgetInternalType::Graph, kMaxRenderableGraphWidgets},
51 };
52
53 constexpr angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeWidgetOffsets = {
54 {WidgetInternalType::Text, 0},
55 {WidgetInternalType::Graph, kMaxRenderableTextWidgets},
56 };
57
58 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
59
60 // Structure matching buffer in vulkan/shaders/src/OverlayCull.comp.
61 struct WidgetCoordinates
62 {
63 uint32_t coordinates[kMaxRenderableTextWidgets + kMaxRenderableGraphWidgets][4];
64 };
65
66 // Structures matching buffers in vulkan/shaders/src/OverlayDraw.comp.
67 struct TextWidgetData
68 {
69 uint32_t coordinates[4];
70 float color[4];
71 uint32_t fontSize[3];
72 uint32_t padding;
73 uint8_t text[kMaxTextLength];
74 };
75
76 struct GraphWidgetData
77 {
78 uint32_t coordinates[4];
79 float color[4];
80 uint32_t valueWidth;
81 uint32_t padding[3];
82 uint32_t values[kMaxGraphDataSize];
83 };
84
85 struct TextWidgets
86 {
87 TextWidgetData widgets[kMaxRenderableTextWidgets];
88 };
89
90 struct GraphWidgets
91 {
92 GraphWidgetData widgets[kMaxRenderableGraphWidgets];
93 };
94
95 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
96
GetWidgetCoord(int32_t src,uint32_t extent)97 uint32_t GetWidgetCoord(int32_t src, uint32_t extent)
98 {
99 int32_t dst = src < 0 ? extent + src : src;
100
101 return std::min<uint32_t>(std::max(dst, 0), extent - 1);
102 }
103
GetWidgetCoordinates(const int32_t srcCoords[4],const gl::Extents & imageExtent,uint32_t dstCoordsOut[4])104 void GetWidgetCoordinates(const int32_t srcCoords[4],
105 const gl::Extents &imageExtent,
106 uint32_t dstCoordsOut[4])
107 {
108 dstCoordsOut[0] = GetWidgetCoord(srcCoords[0], imageExtent.width);
109 dstCoordsOut[1] = GetWidgetCoord(srcCoords[1], imageExtent.height);
110 dstCoordsOut[2] = GetWidgetCoord(srcCoords[2], imageExtent.width);
111 dstCoordsOut[3] = GetWidgetCoord(srcCoords[3], imageExtent.height);
112 }
113
GetWidgetColor(const float srcColor[4],float dstColor[4])114 void GetWidgetColor(const float srcColor[4], float dstColor[4])
115 {
116 memcpy(dstColor, srcColor, 4 * sizeof(dstColor[0]));
117 }
118
GetTextFontSize(int srcFontSize,uint32_t dstFontSize[3])119 void GetTextFontSize(int srcFontSize, uint32_t dstFontSize[3])
120 {
121 // .xy contains the font glyph width/height
122 dstFontSize[0] = overlay::kFontGlyphWidths[srcFontSize];
123 dstFontSize[1] = overlay::kFontGlyphHeights[srcFontSize];
124 // .z contains the layer
125 dstFontSize[2] = srcFontSize;
126 }
127
GetGraphValueWidth(const int32_t srcCoords[4],size_t valueCount,uint32_t * dstValueWidth)128 void GetGraphValueWidth(const int32_t srcCoords[4], size_t valueCount, uint32_t *dstValueWidth)
129 {
130 const int32_t graphWidth = std::abs(srcCoords[2] - srcCoords[0]);
131
132 // If valueCount doesn't divide graphWidth, the graph bars won't fit well in its frame.
133 // Fix initOverlayWidgets() in that case.
134 ASSERT(graphWidth % valueCount == 0);
135
136 *dstValueWidth = graphWidth / valueCount;
137 }
138
GetTextString(const std::string & src,uint8_t textOut[kMaxTextLength])139 void GetTextString(const std::string &src, uint8_t textOut[kMaxTextLength])
140 {
141 for (size_t i = 0; i < src.length() && i < kMaxTextLength; ++i)
142 {
143 // The font image has 96 ASCII characters starting from ' '.
144 textOut[i] = src[i] - ' ';
145 }
146 }
147
GetGraphValues(const std::vector<size_t> srcValues,size_t startIndex,float scale,uint32_t valuesOut[kMaxGraphDataSize])148 void GetGraphValues(const std::vector<size_t> srcValues,
149 size_t startIndex,
150 float scale,
151 uint32_t valuesOut[kMaxGraphDataSize])
152 {
153 ASSERT(srcValues.size() <= kMaxGraphDataSize);
154
155 for (size_t i = 0; i < srcValues.size(); ++i)
156 {
157 size_t index = (startIndex + i) % srcValues.size();
158 valuesOut[i] = static_cast<uint32_t>(srcValues[index] * scale);
159 }
160 }
161
CreateHistogram(const std::vector<size_t> values)162 std::vector<size_t> CreateHistogram(const std::vector<size_t> values)
163 {
164 std::vector<size_t> histogram(values.size(), 0);
165
166 for (size_t rank : values)
167 {
168 ++histogram[rank];
169 }
170
171 return histogram;
172 }
173
174 using OverlayWidgetCounts = angle::PackedEnumMap<WidgetInternalType, size_t>;
175 using AppendWidgetDataFunc = void (*)(const overlay::Widget *widget,
176 const gl::Extents &imageExtent,
177 TextWidgetData *textWidget,
178 GraphWidgetData *graphWidget,
179 OverlayWidgetCounts *widgetCounts);
180 } // namespace
181
182 namespace overlay_impl
183 {
184 #define ANGLE_DECLARE_APPEND_WIDGET_PROC(WIDGET_ID) \
185 static void Append##WIDGET_ID(const overlay::Widget *widget, const gl::Extents &imageExtent, \
186 TextWidgetData *textWidget, GraphWidgetData *graphWidget, \
187 OverlayWidgetCounts *widgetCounts);
188
189 // This class interprets the generic data collected in every element into a human-understandable
190 // widget. This often means generating text specific to this item and scaling graph data to
191 // something sensible.
192 class AppendWidgetDataHelper
193 {
194 public:
195 ANGLE_WIDGET_ID_X(ANGLE_DECLARE_APPEND_WIDGET_PROC)
196
197 private:
198 static std::ostream &OutputPerSecond(std::ostream &out, const overlay::PerSecond *perSecond);
199
200 static std::ostream &OutputText(std::ostream &out, const overlay::Text *text);
201
202 static std::ostream &OutputCount(std::ostream &out, const overlay::Count *count);
203
204 static void AppendTextCommon(const overlay::Widget *widget,
205 const gl::Extents &imageExtent,
206 const std::string &text,
207 TextWidgetData *textWidget,
208 OverlayWidgetCounts *widgetCounts);
209
210 using FormatGraphTitleFunc = std::function<std::string(size_t maxValue)>;
211 static void AppendRunningGraphCommon(const overlay::Widget *widget,
212 const gl::Extents &imageExtent,
213 TextWidgetData *textWidget,
214 GraphWidgetData *graphWidget,
215 OverlayWidgetCounts *widgetCounts,
216 FormatGraphTitleFunc formatFunc);
217
218 using FormatHistogramTitleFunc =
219 std::function<std::string(size_t peakRange, size_t maxValueRange, size_t numRanges)>;
220 static void AppendRunningHistogramCommon(const overlay::Widget *widget,
221 const gl::Extents &imageExtent,
222 TextWidgetData *textWidget,
223 GraphWidgetData *graphWidget,
224 OverlayWidgetCounts *widgetCounts,
225 FormatHistogramTitleFunc formatFunc);
226
227 static void AppendGraphCommon(const overlay::Widget *widget,
228 const gl::Extents &imageExtent,
229 const std::vector<size_t> runningValues,
230 size_t startIndex,
231 float scale,
232 GraphWidgetData *graphWidget,
233 OverlayWidgetCounts *widgetCounts);
234 };
235
AppendTextCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,const std::string & text,TextWidgetData * textWidget,OverlayWidgetCounts * widgetCounts)236 void AppendWidgetDataHelper::AppendTextCommon(const overlay::Widget *widget,
237 const gl::Extents &imageExtent,
238 const std::string &text,
239 TextWidgetData *textWidget,
240 OverlayWidgetCounts *widgetCounts)
241 {
242 GetWidgetCoordinates(widget->coords, imageExtent, textWidget->coordinates);
243 GetWidgetColor(widget->color, textWidget->color);
244 GetTextFontSize(widget->fontSize, textWidget->fontSize);
245 GetTextString(text, textWidget->text);
246
247 ++(*widgetCounts)[WidgetInternalType::Text];
248 }
249
AppendGraphCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,const std::vector<size_t> runningValues,size_t startIndex,float scale,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)250 void AppendWidgetDataHelper::AppendGraphCommon(const overlay::Widget *widget,
251 const gl::Extents &imageExtent,
252 const std::vector<size_t> runningValues,
253 size_t startIndex,
254 float scale,
255 GraphWidgetData *graphWidget,
256 OverlayWidgetCounts *widgetCounts)
257 {
258 const overlay::RunningGraph *widgetAsGraph = static_cast<const overlay::RunningGraph *>(widget);
259
260 GetWidgetCoordinates(widget->coords, imageExtent, graphWidget->coordinates);
261 GetWidgetColor(widget->color, graphWidget->color);
262 GetGraphValueWidth(widget->coords, widgetAsGraph->runningValues.size(),
263 &graphWidget->valueWidth);
264 GetGraphValues(runningValues, startIndex, scale, graphWidget->values);
265
266 ++(*widgetCounts)[WidgetInternalType::Graph];
267 }
268
AppendRunningGraphCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts,AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)269 void AppendWidgetDataHelper::AppendRunningGraphCommon(
270 const overlay::Widget *widget,
271 const gl::Extents &imageExtent,
272 TextWidgetData *textWidget,
273 GraphWidgetData *graphWidget,
274 OverlayWidgetCounts *widgetCounts,
275 AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)
276 {
277 const overlay::RunningGraph *graph = static_cast<const overlay::RunningGraph *>(widget);
278
279 const size_t maxValue =
280 *std::max_element(graph->runningValues.begin(), graph->runningValues.end());
281 const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
282 const float graphScale = static_cast<float>(graphHeight) / maxValue;
283
284 AppendGraphCommon(widget, imageExtent, graph->runningValues, graph->lastValueIndex + 1,
285 graphScale, graphWidget, widgetCounts);
286
287 if ((*widgetCounts)[WidgetInternalType::Text] <
288 kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
289 {
290 std::string text = formatFunc(maxValue);
291 AppendTextCommon(&graph->description, imageExtent, text, textWidget, widgetCounts);
292 }
293 }
294
295 // static
AppendRunningHistogramCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts,FormatHistogramTitleFunc formatFunc)296 void AppendWidgetDataHelper::AppendRunningHistogramCommon(const overlay::Widget *widget,
297 const gl::Extents &imageExtent,
298 TextWidgetData *textWidget,
299 GraphWidgetData *graphWidget,
300 OverlayWidgetCounts *widgetCounts,
301 FormatHistogramTitleFunc formatFunc)
302 {
303 const overlay::RunningHistogram *runningHistogram =
304 static_cast<const overlay::RunningHistogram *>(widget);
305
306 std::vector<size_t> histogram = CreateHistogram(runningHistogram->runningValues);
307 auto peakRangeIt = std::max_element(histogram.rbegin(), histogram.rend());
308 const size_t peakRangeValue = *peakRangeIt;
309 const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
310 const float graphScale = static_cast<float>(graphHeight) / peakRangeValue;
311 auto maxValueIter =
312 std::find_if(histogram.rbegin(), histogram.rend(), [](size_t value) { return value != 0; });
313
314 AppendGraphCommon(widget, imageExtent, histogram, 0, graphScale, graphWidget, widgetCounts);
315
316 if ((*widgetCounts)[WidgetInternalType::Text] <
317 kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
318 {
319 size_t peakRange = std::distance(peakRangeIt, histogram.rend() - 1);
320 size_t maxValueRange = std::distance(maxValueIter, histogram.rend() - 1);
321
322 std::string text = formatFunc(peakRange, maxValueRange, histogram.size());
323 AppendTextCommon(&runningHistogram->description, imageExtent, text, textWidget,
324 widgetCounts);
325 }
326 }
327
AppendFPS(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)328 void AppendWidgetDataHelper::AppendFPS(const overlay::Widget *widget,
329 const gl::Extents &imageExtent,
330 TextWidgetData *textWidget,
331 GraphWidgetData *graphWidget,
332 OverlayWidgetCounts *widgetCounts)
333 {
334 const overlay::PerSecond *fps = static_cast<const overlay::PerSecond *>(widget);
335 std::ostringstream text;
336 text << "FPS: ";
337 OutputPerSecond(text, fps);
338
339 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
340 }
341
AppendVulkanLastValidationMessage(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)342 void AppendWidgetDataHelper::AppendVulkanLastValidationMessage(const overlay::Widget *widget,
343 const gl::Extents &imageExtent,
344 TextWidgetData *textWidget,
345 GraphWidgetData *graphWidget,
346 OverlayWidgetCounts *widgetCounts)
347 {
348 const overlay::Text *lastValidationMessage = static_cast<const overlay::Text *>(widget);
349 std::ostringstream text;
350 text << "Last VVL Message: ";
351 OutputText(text, lastValidationMessage);
352
353 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
354 }
355
AppendVulkanValidationMessageCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)356 void AppendWidgetDataHelper::AppendVulkanValidationMessageCount(const overlay::Widget *widget,
357 const gl::Extents &imageExtent,
358 TextWidgetData *textWidget,
359 GraphWidgetData *graphWidget,
360 OverlayWidgetCounts *widgetCounts)
361 {
362 const overlay::Count *validationMessageCount = static_cast<const overlay::Count *>(widget);
363 std::ostringstream text;
364 text << "VVL Message Count: ";
365 OutputCount(text, validationMessageCount);
366
367 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
368 }
369
AppendVulkanRenderPassCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)370 void AppendWidgetDataHelper::AppendVulkanRenderPassCount(const overlay::Widget *widget,
371 const gl::Extents &imageExtent,
372 TextWidgetData *textWidget,
373 GraphWidgetData *graphWidget,
374 OverlayWidgetCounts *widgetCounts)
375 {
376 auto format = [](size_t maxValue) {
377 std::ostringstream text;
378 text << "RenderPass Count (Max: " << maxValue << ")";
379 return text.str();
380 };
381
382 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
383 }
384
AppendVulkanSecondaryCommandBufferPoolWaste(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)385 void AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste(
386 const overlay::Widget *widget,
387 const gl::Extents &imageExtent,
388 TextWidgetData *textWidget,
389 GraphWidgetData *graphWidget,
390 OverlayWidgetCounts *widgetCounts)
391 {
392 auto format = [](size_t peakRange, size_t maxValueRange, size_t numRanges) {
393 std::ostringstream text;
394 size_t peakPercent = (peakRange * 100 + 50) / numRanges;
395 text << "CB Pool Waste (Peak: " << peakPercent << "%)";
396 return text.str();
397 };
398
399 AppendRunningHistogramCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts,
400 format);
401 }
402
AppendVulkanRenderPassBufferCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)403 void AppendWidgetDataHelper::AppendVulkanRenderPassBufferCount(const overlay::Widget *widget,
404 const gl::Extents &imageExtent,
405 TextWidgetData *textWidget,
406 GraphWidgetData *graphWidget,
407 OverlayWidgetCounts *widgetCounts)
408 {
409 auto format = [](size_t peakRange, size_t maxValueRange, size_t numRanges) {
410 std::ostringstream text;
411 text << "RP VkBuffers (Peak: " << peakRange << ", Max: " << maxValueRange << ")";
412 return text.str();
413 };
414
415 AppendRunningHistogramCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts,
416 format);
417 }
418
AppendVulkanWriteDescriptorSetCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)419 void AppendWidgetDataHelper::AppendVulkanWriteDescriptorSetCount(const overlay::Widget *widget,
420 const gl::Extents &imageExtent,
421 TextWidgetData *textWidget,
422 GraphWidgetData *graphWidget,
423 OverlayWidgetCounts *widgetCounts)
424 {
425 auto format = [](size_t maxValue) {
426 std::ostringstream text;
427 text << "WriteDescriptorSet Count (Max: " << maxValue << ")";
428 return text.str();
429 };
430
431 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
432 }
433
AppendVulkanDescriptorSetAllocations(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)434 void AppendWidgetDataHelper::AppendVulkanDescriptorSetAllocations(const overlay::Widget *widget,
435 const gl::Extents &imageExtent,
436 TextWidgetData *textWidget,
437 GraphWidgetData *graphWidget,
438 OverlayWidgetCounts *widgetCounts)
439 {
440 auto format = [](size_t maxValue) {
441 std::ostringstream text;
442 text << "Descriptor Set Allocations (Max: " << maxValue << ")";
443 return text.str();
444 };
445
446 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
447 }
448
AppendVulkanShaderBufferDSHitRate(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)449 void AppendWidgetDataHelper::AppendVulkanShaderBufferDSHitRate(const overlay::Widget *widget,
450 const gl::Extents &imageExtent,
451 TextWidgetData *textWidget,
452 GraphWidgetData *graphWidget,
453 OverlayWidgetCounts *widgetCounts)
454 {
455 auto format = [](size_t maxValue) {
456 std::ostringstream text;
457 text << "Shader Buffer DS Hit Rate (Max: " << maxValue << "%)";
458 return text.str();
459 };
460
461 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
462 }
463
AppendVulkanDynamicBufferAllocations(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)464 void AppendWidgetDataHelper::AppendVulkanDynamicBufferAllocations(const overlay::Widget *widget,
465 const gl::Extents &imageExtent,
466 TextWidgetData *textWidget,
467 GraphWidgetData *graphWidget,
468 OverlayWidgetCounts *widgetCounts)
469 {
470 auto format = [](size_t maxValue) {
471 std::ostringstream text;
472 text << "DynamicBuffer Allocations (Max: " << maxValue << ")";
473 return text.str();
474 };
475
476 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
477 }
478
OutputPerSecond(std::ostream & out,const overlay::PerSecond * perSecond)479 std::ostream &AppendWidgetDataHelper::OutputPerSecond(std::ostream &out,
480 const overlay::PerSecond *perSecond)
481 {
482 return out << perSecond->lastPerSecondCount;
483 }
484
OutputText(std::ostream & out,const overlay::Text * text)485 std::ostream &AppendWidgetDataHelper::OutputText(std::ostream &out, const overlay::Text *text)
486 {
487 return out << text->text;
488 }
489
OutputCount(std::ostream & out,const overlay::Count * count)490 std::ostream &AppendWidgetDataHelper::OutputCount(std::ostream &out, const overlay::Count *count)
491 {
492 return out << count->count;
493 }
494 } // namespace overlay_impl
495
496 namespace
497 {
498 #define ANGLE_APPEND_WIDGET_MAP_PROC(WIDGET_ID) \
499 {WidgetId::WIDGET_ID, overlay_impl::AppendWidgetDataHelper::Append##WIDGET_ID},
500
501 constexpr angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = {
502 ANGLE_WIDGET_ID_X(ANGLE_APPEND_WIDGET_MAP_PROC)};
503 } // namespace
504
505 namespace overlay
506 {
RunningGraph(size_t n)507 RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {}
508 RunningGraph::~RunningGraph() = default;
509 } // namespace overlay
510
getWidgetCoordinatesBufferSize() const511 size_t OverlayState::getWidgetCoordinatesBufferSize() const
512 {
513 return sizeof(WidgetCoordinates);
514 }
515
getTextWidgetsBufferSize() const516 size_t OverlayState::getTextWidgetsBufferSize() const
517 {
518 return sizeof(TextWidgets);
519 }
520
getGraphWidgetsBufferSize() const521 size_t OverlayState::getGraphWidgetsBufferSize() const
522 {
523 return sizeof(GraphWidgets);
524 }
525
fillEnabledWidgetCoordinates(const gl::Extents & imageExtents,uint8_t * enabledWidgetsPtr) const526 void OverlayState::fillEnabledWidgetCoordinates(const gl::Extents &imageExtents,
527 uint8_t *enabledWidgetsPtr) const
528 {
529 WidgetCoordinates *enabledWidgets = reinterpret_cast<WidgetCoordinates *>(enabledWidgetsPtr);
530 memset(enabledWidgets, 0, sizeof(*enabledWidgets));
531
532 OverlayWidgetCounts widgetCounts = {};
533
534 for (const std::unique_ptr<overlay::Widget> &widget : mOverlayWidgets)
535 {
536 if (!widget->enabled)
537 {
538 continue;
539 }
540
541 WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type];
542 ASSERT(internalType != WidgetInternalType::InvalidEnum);
543
544 if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType])
545 {
546 continue;
547 }
548
549 size_t writeIndex =
550 kWidgetInternalTypeWidgetOffsets[internalType] + widgetCounts[internalType]++;
551
552 GetWidgetCoordinates(widget->coords, imageExtents, enabledWidgets->coordinates[writeIndex]);
553
554 // Graph widgets have a text widget attached as well.
555 if (internalType == WidgetInternalType::Graph)
556 {
557 WidgetInternalType textType = WidgetInternalType::Text;
558 if (widgetCounts[textType] >= kWidgetInternalTypeMaxWidgets[textType])
559 {
560 continue;
561 }
562
563 const overlay::RunningGraph *widgetAsGraph =
564 static_cast<const overlay::RunningGraph *>(widget.get());
565 writeIndex = kWidgetInternalTypeWidgetOffsets[textType] + widgetCounts[textType]++;
566
567 GetWidgetCoordinates(widgetAsGraph->description.coords, imageExtents,
568 enabledWidgets->coordinates[writeIndex]);
569 }
570 }
571 }
572
fillWidgetData(const gl::Extents & imageExtents,uint8_t * textData,uint8_t * graphData) const573 void OverlayState::fillWidgetData(const gl::Extents &imageExtents,
574 uint8_t *textData,
575 uint8_t *graphData) const
576 {
577 TextWidgets *textWidgets = reinterpret_cast<TextWidgets *>(textData);
578 GraphWidgets *graphWidgets = reinterpret_cast<GraphWidgets *>(graphData);
579
580 memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets));
581 memset(graphWidgets, 0, sizeof(*graphWidgets));
582
583 OverlayWidgetCounts widgetCounts = {};
584
585 for (WidgetId id : angle::AllEnums<WidgetId>())
586 {
587 const std::unique_ptr<overlay::Widget> &widget = mOverlayWidgets[id];
588 if (!widget->enabled)
589 {
590 continue;
591 }
592
593 WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type];
594 ASSERT(internalType != WidgetInternalType::InvalidEnum);
595
596 if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType])
597 {
598 continue;
599 }
600
601 AppendWidgetDataFunc appendFunc = kWidgetIdToAppendDataFuncMap[id];
602 ASSERT(appendFunc);
603 appendFunc(widget.get(), imageExtents,
604 &textWidgets->widgets[widgetCounts[WidgetInternalType::Text]],
605 &graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]], &widgetCounts);
606 }
607 }
608
609 } // namespace gl
610