//
// 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 "libANGLE/Overlay.h"
#include "libANGLE/Overlay_font_autogen.h"

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          = 64;

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

CONSTEXPR angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeWidgetOffsets = {
    {WidgetInternalType::Text, 0},
    {WidgetInternalType::Graph, kMaxRenderableTextWidgets},
};

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);
    dstCoordsOut[1] = GetWidgetCoord(srcCoords[1], imageExtent.height);
    dstCoordsOut[2] = GetWidgetCoord(srcCoords[2], imageExtent.width);
    dstCoordsOut[3] = GetWidgetCoord(srcCoords[3], imageExtent.height);
}

void GetWidgetColor(const float srcColor[4], float dstColor[4])
{
    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::kFontGlyphWidths[srcFontSize];
    dstFontSize[1] = overlay::kFontGlyphHeights[srcFontSize];
    // .z contains the layer
    dstFontSize[2] = srcFontSize;
}

void GetGraphValueWidth(const int32_t srcCoords[4], size_t valueCount, uint32_t *dstValueWidth)
{
    const int32_t graphWidth = std::abs(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 96 ASCII characters starting from ' '.
        textOut[i] = src[i] - ' ';
    }
}

void GetGraphValues(const std::vector<size_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();
        valuesOut[i] = static_cast<uint32_t>(srcValues[index] * scale);
    }
}

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

    for (size_t rank : values)
    {
        ++histogram[rank];
    }

    return histogram;
}

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

namespace overlay_impl
{
// 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:
    static void AppendFPS(const overlay::Widget *widget,
                          const gl::Extents &imageExtent,
                          TextWidgetData *textWidget,
                          GraphWidgetData *graphWidget,
                          OverlayWidgetCounts *widgetCounts);
    static void AppendVulkanLastValidationMessage(const overlay::Widget *widget,
                                                  const gl::Extents &imageExtent,
                                                  TextWidgetData *textWidget,
                                                  GraphWidgetData *graphWidget,
                                                  OverlayWidgetCounts *widgetCounts);
    static void AppendVulkanValidationMessageCount(const overlay::Widget *widget,
                                                   const gl::Extents &imageExtent,
                                                   TextWidgetData *textWidget,
                                                   GraphWidgetData *graphWidget,
                                                   OverlayWidgetCounts *widgetCounts);
    static void AppendVulkanCommandGraphSize(const overlay::Widget *widget,
                                             const gl::Extents &imageExtent,
                                             TextWidgetData *textWidget,
                                             GraphWidgetData *graphWidget,
                                             OverlayWidgetCounts *widgetCounts);
    static void AppendVulkanSecondaryCommandBufferPoolWaste(const overlay::Widget *widget,
                                                            const gl::Extents &imageExtent,
                                                            TextWidgetData *textWidget,
                                                            GraphWidgetData *graphWidget,
                                                            OverlayWidgetCounts *widgetCounts);

  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);

    static void AppendGraphCommon(const overlay::Widget *widget,
                                  const gl::Extents &imageExtent,
                                  const std::vector<size_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<size_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::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::AppendVulkanCommandGraphSize(const overlay::Widget *widget,
                                                          const gl::Extents &imageExtent,
                                                          TextWidgetData *textWidget,
                                                          GraphWidgetData *graphWidget,
                                                          OverlayWidgetCounts *widgetCounts)
{
    const overlay::RunningGraph *commandGraphSize =
        static_cast<const overlay::RunningGraph *>(widget);

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

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

    if ((*widgetCounts)[WidgetInternalType::Text] <
        kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
    {
        std::ostringstream text;
        text << "Command Graph Size (Max: " << maxValue << ")";
        AppendTextCommon(&commandGraphSize->description, imageExtent, text.str(), textWidget,
                         widgetCounts);
    }
}

void AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste(
    const overlay::Widget *widget,
    const gl::Extents &imageExtent,
    TextWidgetData *textWidget,
    GraphWidgetData *graphWidget,
    OverlayWidgetCounts *widgetCounts)
{
    const overlay::RunningHistogram *secondaryCommandBufferPoolWaste =
        static_cast<const overlay::RunningHistogram *>(widget);

    std::vector<size_t> histogram = CreateHistogram(secondaryCommandBufferPoolWaste->runningValues);
    auto maxValueIter             = std::max_element(histogram.rbegin(), histogram.rend());
    const size_t maxValue         = *maxValueIter;
    const int32_t graphHeight     = std::abs(widget->coords[3] - widget->coords[1]);
    const float graphScale        = static_cast<float>(graphHeight) / maxValue;

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

    if ((*widgetCounts)[WidgetInternalType::Text] <
        kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
    {
        std::ostringstream text;
        size_t peak        = std::distance(maxValueIter, histogram.rend() - 1);
        size_t peakPercent = (peak * 100 + 50) / histogram.size();

        text << "CB Pool Waste (Peak: " << peakPercent << "%)";
        AppendTextCommon(&secondaryCommandBufferPoolWaste->description, 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
{
CONSTEXPR angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = {
    {WidgetId::FPS, overlay_impl::AppendWidgetDataHelper::AppendFPS},
    {WidgetId::VulkanLastValidationMessage,
     overlay_impl::AppendWidgetDataHelper::AppendVulkanLastValidationMessage},
    {WidgetId::VulkanValidationMessageCount,
     overlay_impl::AppendWidgetDataHelper::AppendVulkanValidationMessageCount},
    {WidgetId::VulkanCommandGraphSize,
     overlay_impl::AppendWidgetDataHelper::AppendVulkanCommandGraphSize},
    {WidgetId::VulkanSecondaryCommandBufferPoolWaste,
     overlay_impl::AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste},
};
}

namespace overlay
{
RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {}
RunningGraph::~RunningGraph() = default;
}  // 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::fillEnabledWidgetCoordinates(const gl::Extents &imageExtents,
                                                uint8_t *enabledWidgetsPtr) const
{
    WidgetCoordinates *enabledWidgets = reinterpret_cast<WidgetCoordinates *>(enabledWidgetsPtr);
    memset(enabledWidgets, 0, sizeof(*enabledWidgets));

    OverlayWidgetCounts widgetCounts = {};

    for (const std::unique_ptr<overlay::Widget> &widget : mOverlayWidgets)
    {
        if (!widget->enabled)
        {
            continue;
        }

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

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

        size_t writeIndex =
            kWidgetInternalTypeWidgetOffsets[internalType] + widgetCounts[internalType]++;

        GetWidgetCoordinates(widget->coords, imageExtents, enabledWidgets->coordinates[writeIndex]);

        // Graph widgets have a text widget attached as well.
        if (internalType == WidgetInternalType::Graph)
        {
            WidgetInternalType textType = WidgetInternalType::Text;
            if (widgetCounts[textType] >= kWidgetInternalTypeMaxWidgets[textType])
            {
                continue;
            }

            const overlay::RunningGraph *widgetAsGraph =
                static_cast<const overlay::RunningGraph *>(widget.get());
            writeIndex = kWidgetInternalTypeWidgetOffsets[textType] + widgetCounts[textType]++;

            GetWidgetCoordinates(widgetAsGraph->description.coords, imageExtents,
                                 enabledWidgets->coordinates[writeIndex]);
        }
    }
}

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

    memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets));
    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];
        appendFunc(widget.get(), imageExtents,
                   &textWidgets->widgets[widgetCounts[WidgetInternalType::Text]],
                   &graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]], &widgetCounts);
    }
}

}  // namespace gl
