//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// OverlayWidgets.cpp:
//    Implements functions that interpret widget data.  Data formats and limits correspond to the
//    Vulkan implementation (as the only implementation).  They are generic enough so other backends
//    could respect them too, if they implement the overlay.
//

#include "common/unsafe_buffers.h"
#include "libANGLE/Overlay.h"
#include "libANGLE/Overlay_font_autogen.h"

#include <functional>

namespace gl
{
namespace
{
// Internally, every widget is either Text or Graph.
enum class WidgetInternalType
{
    Text,
    Graph,

    InvalidEnum,
    EnumCount = InvalidEnum,
};

// A map that says how the API-facing widget types map to internal types.
constexpr angle::PackedEnumMap<WidgetType, WidgetInternalType> kWidgetTypeToInternalMap = {
    {WidgetType::Count, WidgetInternalType::Text},
    {WidgetType::Text, WidgetInternalType::Text},
    {WidgetType::PerSecond, WidgetInternalType::Text},
    {WidgetType::RunningGraph, WidgetInternalType::Graph},
    {WidgetType::RunningHistogram, WidgetInternalType::Graph},
};

// Structures and limits matching uniform buffers in vulkan/shaders/src/OverlayDraw.comp.  The size
// of text and graph widgets is chosen such that they could fit in uniform buffers with minimum
// required Vulkan size.
constexpr size_t kMaxRenderableTextWidgets  = 32;
constexpr size_t kMaxRenderableGraphWidgets = 32;
constexpr size_t kMaxTextLength             = 256;
constexpr size_t kMaxGraphDataSize          = 256;

constexpr angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeMaxWidgets = {
    {WidgetInternalType::Text, kMaxRenderableTextWidgets},
    {WidgetInternalType::Graph, kMaxRenderableGraphWidgets},
};

ANGLE_ENABLE_STRUCT_PADDING_WARNINGS

// Structure matching buffer in vulkan/shaders/src/OverlayCull.comp.
struct WidgetCoordinates
{
    uint32_t coordinates[kMaxRenderableTextWidgets + kMaxRenderableGraphWidgets][4];
};

// Structures matching buffers in vulkan/shaders/src/OverlayDraw.comp.
struct TextWidgetData
{
    uint32_t coordinates[4];
    float color[4];
    uint32_t fontSize[3];
    uint32_t padding;
    uint8_t text[kMaxTextLength];
};

struct GraphWidgetData
{
    uint32_t coordinates[4];
    float color[4];
    uint32_t valueWidth;
    uint32_t padding[3];
    uint32_t values[kMaxGraphDataSize];
};

struct TextWidgets
{
    TextWidgetData widgets[kMaxRenderableTextWidgets];
};

struct GraphWidgets
{
    GraphWidgetData widgets[kMaxRenderableGraphWidgets];
};

ANGLE_DISABLE_STRUCT_PADDING_WARNINGS

uint32_t GetWidgetCoord(int32_t src, uint32_t extent)
{
    int32_t dst = src < 0 ? extent + src : src;

    return std::min<uint32_t>(std::max(dst, 0), extent - 1);
}

void GetWidgetCoordinates(const int32_t srcCoords[4],
                          const gl::Extents &imageExtent,
                          uint32_t dstCoordsOut[4])
{
    dstCoordsOut[0] = GetWidgetCoord(srcCoords[0], imageExtent.width);
    ANGLE_UNSAFE_TODO(dstCoordsOut[1]) =
        GetWidgetCoord(ANGLE_UNSAFE_TODO(srcCoords[1]), imageExtent.height);
    ANGLE_UNSAFE_TODO(dstCoordsOut[2]) =
        GetWidgetCoord(ANGLE_UNSAFE_TODO(srcCoords[2]), imageExtent.width);
    ANGLE_UNSAFE_TODO(dstCoordsOut[3]) =
        GetWidgetCoord(ANGLE_UNSAFE_TODO(srcCoords[3]), imageExtent.height);
}

void GetWidgetColor(const float srcColor[4], float dstColor[4])
{
    ANGLE_UNSAFE_TODO(memcpy(dstColor, srcColor, 4 * sizeof(dstColor[0])));
}

void GetTextFontSize(int srcFontSize, uint32_t dstFontSize[3])
{
    // .xy contains the font glyph width/height
    dstFontSize[0] = overlay::kFontGlyphWidth >> srcFontSize;
    ANGLE_UNSAFE_TODO(dstFontSize[1]) = overlay::kFontGlyphHeight >> srcFontSize;
    // .z contains the mip
    ANGLE_UNSAFE_TODO(dstFontSize[2]) = srcFontSize;
}

void GetGraphValueWidth(const int32_t srcCoords[4], size_t valueCount, uint32_t *dstValueWidth)
{
    const int32_t graphWidth = std::abs(ANGLE_UNSAFE_TODO(srcCoords[2]) - srcCoords[0]);

    // If valueCount doesn't divide graphWidth, the graph bars won't fit well in its frame.
    // Fix initOverlayWidgets() in that case.
    ASSERT(graphWidth % valueCount == 0);

    *dstValueWidth = graphWidth / valueCount;
}

void GetTextString(const std::string &src, uint8_t textOut[kMaxTextLength])
{
    for (size_t i = 0; i < src.length() && i < kMaxTextLength; ++i)
    {
        // The font image has 95 ASCII characters starting from ' '.
        ANGLE_UNSAFE_TODO(textOut[i]) = src[i] - ' ';
    }
}

void GetGraphValues(const std::vector<uint64_t> srcValues,
                    size_t startIndex,
                    float scale,
                    uint32_t valuesOut[kMaxGraphDataSize])
{
    ASSERT(srcValues.size() <= kMaxGraphDataSize);

    for (size_t i = 0; i < srcValues.size(); ++i)
    {
        size_t index = (startIndex + i) % srcValues.size();
        ANGLE_UNSAFE_TODO(valuesOut[i]) = static_cast<uint32_t>(srcValues[index] * scale);
    }
}

std::vector<uint64_t> CreateHistogram(const std::vector<uint64_t> values)
{
    std::vector<uint64_t> histogram(values.size(), 0);

    for (uint64_t rank : values)
    {
        ++histogram[static_cast<size_t>(rank)];
    }

    return histogram;
}

using OverlayWidgetCounts  = angle::PackedEnumMap<WidgetInternalType, uint32_t>;
using AppendWidgetDataFunc = void (*)(const overlay::Widget *widget,
                                      const gl::Extents &imageExtent,
                                      TextWidgetData *textWidget,
                                      GraphWidgetData *graphWidget,
                                      OverlayWidgetCounts *widgetCounts);
}  // namespace

namespace overlay_impl
{
#define ANGLE_DECLARE_APPEND_WIDGET_PROC(WIDGET_ID)                                              \
    static void Append##WIDGET_ID(const overlay::Widget *widget, const gl::Extents &imageExtent, \
                                  TextWidgetData *textWidget, GraphWidgetData *graphWidget,      \
                                  OverlayWidgetCounts *widgetCounts);

// This class interprets the generic data collected in every element into a human-understandable
// widget.  This often means generating text specific to this item and scaling graph data to
// something sensible.
class AppendWidgetDataHelper
{
  public:
    ANGLE_WIDGET_ID_X(ANGLE_DECLARE_APPEND_WIDGET_PROC)

  private:
    static std::ostream &OutputPerSecond(std::ostream &out, const overlay::PerSecond *perSecond);

    static std::ostream &OutputText(std::ostream &out, const overlay::Text *text);

    static std::ostream &OutputCount(std::ostream &out, const overlay::Count *count);

    static void AppendTextCommon(const overlay::Widget *widget,
                                 const gl::Extents &imageExtent,
                                 const std::string &text,
                                 TextWidgetData *textWidget,
                                 OverlayWidgetCounts *widgetCounts);

    using FormatGraphTitleFunc = std::function<std::string(uint64_t curValue, uint64_t maxValue)>;
    static void AppendRunningGraphCommon(const overlay::Widget *widget,
                                         const gl::Extents &imageExtent,
                                         TextWidgetData *textWidget,
                                         GraphWidgetData *graphWidget,
                                         OverlayWidgetCounts *widgetCounts,
                                         FormatGraphTitleFunc formatFunc);

    using FormatHistogramTitleFunc =
        std::function<std::string(size_t peakRange, size_t maxValueRange, size_t numRanges)>;
    static void AppendRunningHistogramCommon(const overlay::Widget *widget,
                                             const gl::Extents &imageExtent,
                                             TextWidgetData *textWidget,
                                             GraphWidgetData *graphWidget,
                                             OverlayWidgetCounts *widgetCounts,
                                             FormatHistogramTitleFunc formatFunc);

    static void AppendGraphCommon(const overlay::Widget *widget,
                                  const gl::Extents &imageExtent,
                                  const std::vector<uint64_t> runningValues,
                                  size_t startIndex,
                                  float scale,
                                  GraphWidgetData *graphWidget,
                                  OverlayWidgetCounts *widgetCounts);
};

void AppendWidgetDataHelper::AppendTextCommon(const overlay::Widget *widget,
                                              const gl::Extents &imageExtent,
                                              const std::string &text,
                                              TextWidgetData *textWidget,
                                              OverlayWidgetCounts *widgetCounts)
{
    GetWidgetCoordinates(widget->coords, imageExtent, textWidget->coordinates);
    GetWidgetColor(widget->color, textWidget->color);
    GetTextFontSize(widget->fontSize, textWidget->fontSize);
    GetTextString(text, textWidget->text);

    ++(*widgetCounts)[WidgetInternalType::Text];
}

void AppendWidgetDataHelper::AppendGraphCommon(const overlay::Widget *widget,
                                               const gl::Extents &imageExtent,
                                               const std::vector<uint64_t> runningValues,
                                               size_t startIndex,
                                               float scale,
                                               GraphWidgetData *graphWidget,
                                               OverlayWidgetCounts *widgetCounts)
{
    const overlay::RunningGraph *widgetAsGraph = static_cast<const overlay::RunningGraph *>(widget);

    GetWidgetCoordinates(widget->coords, imageExtent, graphWidget->coordinates);
    GetWidgetColor(widget->color, graphWidget->color);
    GetGraphValueWidth(widget->coords, widgetAsGraph->runningValues.size(),
                       &graphWidget->valueWidth);
    GetGraphValues(runningValues, startIndex, scale, graphWidget->values);

    ++(*widgetCounts)[WidgetInternalType::Graph];
}

void AppendWidgetDataHelper::AppendRunningGraphCommon(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts,
    AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)
{
    const overlay::RunningGraph *graph   = static_cast<const overlay::RunningGraph *>(widget);
    const overlay::Widget *matchToWidget = widget->matchToWidget;

    if (matchToWidget == nullptr)
    {
        matchToWidget = widget;
    }
    const overlay::RunningGraph *matchToGraph =
        static_cast<const overlay::RunningGraph *>(matchToWidget);

    const uint64_t maxValue =
        *std::max_element(graph->runningValues.begin(), graph->runningValues.end());
    const uint64_t maxValueInMatchToGraph =
        *std::max_element(matchToGraph->runningValues.begin(), matchToGraph->runningValues.end());
    const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
    const float graphScale    = static_cast<float>(graphHeight) / maxValueInMatchToGraph;

    const size_t graphSize  = graph->runningValues.size();
    const size_t currentIdx = graph->lastValueIndex - 1;

    const uint64_t curValue = graph->runningValues[(graphSize + currentIdx) % graphSize];

    AppendGraphCommon(widget, imageExtent, graph->runningValues, graph->lastValueIndex + 1,
                      graphScale, graphWidget, widgetCounts);

    if ((*widgetCounts)[WidgetInternalType::Text] <
        kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
    {
        std::string text = formatFunc(curValue, maxValue);
        AppendTextCommon(&graph->description, imageExtent, text, textWidget, widgetCounts);
    }
}

// static
void AppendWidgetDataHelper::AppendRunningHistogramCommon(const overlay::Widget *widget,
                                                          const gl::Extents &imageExtent,
                                                          TextWidgetData *textWidget,
                                                          GraphWidgetData *graphWidget,
                                                          OverlayWidgetCounts *widgetCounts,
                                                          FormatHistogramTitleFunc formatFunc)
{
    const overlay::RunningHistogram *runningHistogram =
        static_cast<const overlay::RunningHistogram *>(widget);

    std::vector<uint64_t> histogram = CreateHistogram(runningHistogram->runningValues);
    auto peakRangeIt                = std::max_element(histogram.rbegin(), histogram.rend());
    const uint64_t peakRangeValue   = *peakRangeIt;
    const int32_t graphHeight       = std::abs(widget->coords[3] - widget->coords[1]);
    const float graphScale          = static_cast<float>(graphHeight) / peakRangeValue;
    auto maxValueIter               = std::find_if(histogram.rbegin(), histogram.rend(),
                                                   [](uint64_t value) { return value != 0; });

    AppendGraphCommon(widget, imageExtent, histogram, 0, graphScale, graphWidget, widgetCounts);

    if ((*widgetCounts)[WidgetInternalType::Text] <
        kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
    {
        size_t peakRange     = std::distance(peakRangeIt, histogram.rend() - 1);
        size_t maxValueRange = std::distance(maxValueIter, histogram.rend() - 1);

        std::string text = formatFunc(peakRange, maxValueRange, histogram.size());
        AppendTextCommon(&runningHistogram->description, imageExtent, text, textWidget,
                         widgetCounts);
    }
}

void AppendWidgetDataHelper::AppendFPS(const overlay::Widget *widget,
                                       const gl::Extents &imageExtent,
                                       TextWidgetData *textWidget,
                                       GraphWidgetData *graphWidget,
                                       OverlayWidgetCounts *widgetCounts)
{
    const overlay::PerSecond *fps = static_cast<const overlay::PerSecond *>(widget);
    std::ostringstream text;
    text << "FPS: ";
    OutputPerSecond(text, fps);

    AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
}

void AppendWidgetDataHelper::AppendVulkanLastValidationMessage(const overlay::Widget *widget,
                                                               const gl::Extents &imageExtent,
                                                               TextWidgetData *textWidget,
                                                               GraphWidgetData *graphWidget,
                                                               OverlayWidgetCounts *widgetCounts)
{
    const overlay::Text *lastValidationMessage = static_cast<const overlay::Text *>(widget);
    std::ostringstream text;
    text << "Last VVL Message: ";
    OutputText(text, lastValidationMessage);

    AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
}

void AppendWidgetDataHelper::AppendVulkanValidationMessageCount(const overlay::Widget *widget,
                                                                const gl::Extents &imageExtent,
                                                                TextWidgetData *textWidget,
                                                                GraphWidgetData *graphWidget,
                                                                OverlayWidgetCounts *widgetCounts)
{
    const overlay::Count *validationMessageCount = static_cast<const overlay::Count *>(widget);
    std::ostringstream text;
    text << "VVL Message Count: ";
    OutputCount(text, validationMessageCount);

    AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
}

void AppendWidgetDataHelper::AppendVulkanRenderPassCount(const overlay::Widget *widget,
                                                         const gl::Extents &imageExtent,
                                                         TextWidgetData *textWidget,
                                                         GraphWidgetData *graphWidget,
                                                         OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "RenderPass Count: " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts)
{
    auto format = [](size_t peakRange, size_t maxValueRange, size_t numRanges) {
        std::ostringstream text;
        size_t peakPercent = (peakRange * 100 + 50) / numRanges;
        text << "CB Pool Waste (Peak: " << peakPercent << "%)";
        return text.str();
    };

    AppendRunningHistogramCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts,
                                 format);
}

void AppendWidgetDataHelper::AppendVulkanWriteDescriptorSetCount(const overlay::Widget *widget,
                                                                 const gl::Extents &imageExtent,
                                                                 TextWidgetData *textWidget,
                                                                 GraphWidgetData *graphWidget,
                                                                 OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "WriteDescriptorSet Count: " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanDescriptorSetAllocations(const overlay::Widget *widget,
                                                                  const gl::Extents &imageExtent,
                                                                  TextWidgetData *textWidget,
                                                                  GraphWidgetData *graphWidget,
                                                                  OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Descriptor Set Allocations: " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanShaderResourceDSHitRate(const overlay::Widget *widget,
                                                                 const gl::Extents &imageExtent,
                                                                 TextWidgetData *textWidget,
                                                                 GraphWidgetData *graphWidget,
                                                                 OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Shader Resource DS Hit Rate (Max: " << maxValue << "%)";
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanDynamicBufferAllocations(const overlay::Widget *widget,
                                                                  const gl::Extents &imageExtent,
                                                                  TextWidgetData *textWidget,
                                                                  GraphWidgetData *graphWidget,
                                                                  OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "DynamicBuffer Allocations (Max: " << maxValue << ")";
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanTextureDescriptorCacheSize(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Total Texture Descriptor Cache Size: " << curValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanUniformDescriptorCacheSize(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Total Uniform Descriptor Cache Size: " << curValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanDescriptorCacheSize(const overlay::Widget *widget,
                                                             const gl::Extents &imageExtent,
                                                             TextWidgetData *textWidget,
                                                             GraphWidgetData *graphWidget,
                                                             OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Total Descriptor Cache Size: " << curValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanDescriptorCacheKeySize(const overlay::Widget *widget,
                                                                const gl::Extents &imageExtent,
                                                                TextWidgetData *textWidget,
                                                                GraphWidgetData *graphWidget,
                                                                OverlayWidgetCounts *widgetCounts)
{
    const overlay::Count *countWidget = static_cast<const overlay::Count *>(widget);
    std::ostringstream text;
    double kb = static_cast<double>(countWidget->count) / 1000.0;
    text << "DS Cache Key Size: " << std::fixed << std::setprecision(1) << kb << " kb";

    AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
}

void AppendWidgetDataHelper::AppendVulkanAttemptedSubmissions(const overlay::Widget *widget,
                                                              const gl::Extents &imageExtent,
                                                              TextWidgetData *textWidget,
                                                              GraphWidgetData *graphWidget,
                                                              OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Attempted submissions (peak): " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanActualSubmissions(const overlay::Widget *widget,
                                                           const gl::Extents &imageExtent,
                                                           TextWidgetData *textWidget,
                                                           GraphWidgetData *graphWidget,
                                                           OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Actual submissions (peak): " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanPipelineCacheLookups(const overlay::Widget *widget,
                                                              const gl::Extents &imageExtent,
                                                              TextWidgetData *textWidget,
                                                              GraphWidgetData *graphWidget,
                                                              OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Pipeline Cache Lookups (peak): " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanPipelineCacheMisses(const overlay::Widget *widget,
                                                             const gl::Extents &imageExtent,
                                                             TextWidgetData *textWidget,
                                                             GraphWidgetData *graphWidget,
                                                             OverlayWidgetCounts *widgetCounts)
{
    auto format = [](uint64_t curValue, uint64_t maxValue) {
        std::ostringstream text;
        text << "Pipeline Cache Misses (peak): " << maxValue;
        return text.str();
    };

    AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
}

void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheHitTimeMs(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts)
{
    const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
    std::ostringstream text;
    text << "Total Pipeline Cache Hit Time: ";
    OutputCount(text, totalTime);
    text << "ms";

    AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
}

void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheMissTimeMs(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts)
{
    const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
    std::ostringstream text;
    text << "Total Pipeline Cache Miss Time: ";
    OutputCount(text, totalTime);
    text << "ms";

    AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
}

std::ostream &AppendWidgetDataHelper::OutputPerSecond(std::ostream &out,
                                                      const overlay::PerSecond *perSecond)
{
    return out << perSecond->lastPerSecondCount;
}

std::ostream &AppendWidgetDataHelper::OutputText(std::ostream &out, const overlay::Text *text)
{
    return out << text->text;
}

std::ostream &AppendWidgetDataHelper::OutputCount(std::ostream &out, const overlay::Count *count)
{
    return out << count->count;
}
}  // namespace overlay_impl

namespace
{
#define ANGLE_APPEND_WIDGET_MAP_PROC(WIDGET_ID) \
    {WidgetId::WIDGET_ID, overlay_impl::AppendWidgetDataHelper::Append##WIDGET_ID},

constexpr angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = {
    ANGLE_WIDGET_ID_X(ANGLE_APPEND_WIDGET_MAP_PROC)};
}  // namespace

namespace overlay
{
const Text *Widget::getDescriptionWidget() const
{
    return nullptr;
}
RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {}
RunningGraph::~RunningGraph() = default;
const Text *RunningGraph::getDescriptionWidget() const
{
    return &description;
}
}  // namespace overlay

size_t OverlayState::getWidgetCoordinatesBufferSize() const
{
    return sizeof(WidgetCoordinates);
}

size_t OverlayState::getTextWidgetsBufferSize() const
{
    return sizeof(TextWidgets);
}

size_t OverlayState::getGraphWidgetsBufferSize() const
{
    return sizeof(GraphWidgets);
}

void OverlayState::fillWidgetData(const gl::Extents &imageExtents,
                                  uint8_t *textData,
                                  uint8_t *graphData,
                                  uint32_t *activeTextWidgetCountOut,
                                  uint32_t *activeGraphWidgetCountOut) const
{
    TextWidgets *textWidgets   = reinterpret_cast<TextWidgets *>(textData);
    GraphWidgets *graphWidgets = reinterpret_cast<GraphWidgets *>(graphData);

    ANGLE_UNSAFE_TODO(memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets)));
    ANGLE_UNSAFE_TODO(memset(graphWidgets, 0, sizeof(*graphWidgets)));

    OverlayWidgetCounts widgetCounts = {};

    for (WidgetId id : angle::AllEnums<WidgetId>())
    {
        const std::unique_ptr<overlay::Widget> &widget = mOverlayWidgets[id];
        if (!widget->enabled)
        {
            continue;
        }

        WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type];
        ASSERT(internalType != WidgetInternalType::InvalidEnum);

        if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType])
        {
            continue;
        }

        AppendWidgetDataFunc appendFunc = kWidgetIdToAppendDataFuncMap[id];
        ASSERT(appendFunc);
        appendFunc(
            widget.get(), imageExtents,
            &ANGLE_UNSAFE_TODO(textWidgets->widgets[widgetCounts[WidgetInternalType::Text]]),
            &ANGLE_UNSAFE_TODO(graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]]),
            &widgetCounts);
    }

    *activeTextWidgetCountOut  = widgetCounts[WidgetInternalType::Text];
    *activeGraphWidgetCountOut = widgetCounts[WidgetInternalType::Graph];
}

}  // namespace gl
