/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "utils/StringUtils.h"
#include "Texture.h"

#include <cutils/compiler.h>
#include <GpuMemoryTracker.h>
#include <utils/Trace.h>
#include <array>
#include <sstream>
#include <unordered_set>
#include <vector>

namespace android {
namespace uirenderer {

pthread_t gGpuThread = 0;

#define NUM_TYPES static_cast<int>(GpuObjectType::TypeCount)

const char* TYPE_NAMES[] = {
        "Texture",
        "OffscreenBuffer",
        "Layer",
};

struct TypeStats {
    int totalSize = 0;
    int count = 0;
};

static std::array<TypeStats, NUM_TYPES> gObjectStats;
static std::unordered_set<GpuMemoryTracker*> gObjectSet;

void GpuMemoryTracker::notifySizeChanged(int newSize) {
    int delta = newSize - mSize;
    mSize = newSize;
    gObjectStats[static_cast<int>(mType)].totalSize += delta;
}

void GpuMemoryTracker::startTrackingObject() {
    auto result = gObjectSet.insert(this);
    LOG_ALWAYS_FATAL_IF(!result.second,
            "startTrackingObject() on %p failed, already being tracked!", this);
    gObjectStats[static_cast<int>(mType)].count++;
}

void GpuMemoryTracker::stopTrackingObject() {
    size_t removed = gObjectSet.erase(this);
    LOG_ALWAYS_FATAL_IF(removed != 1,
            "stopTrackingObject removed %zd, is %p not being tracked?",
            removed, this);
    gObjectStats[static_cast<int>(mType)].count--;
}

void GpuMemoryTracker::onGLContextCreated() {
    LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a GL thread? "
            "current = %lu, gl thread = %lu", pthread_self(), gGpuThread);
    gGpuThread = pthread_self();
}

void GpuMemoryTracker::onGLContextDestroyed() {
    gGpuThread = 0;
    if (CC_UNLIKELY(gObjectSet.size() > 0)) {
        std::stringstream os;
        dump(os);
        ALOGE("%s", os.str().c_str());
        LOG_ALWAYS_FATAL("Leaked %zd GPU objects!", gObjectSet.size());
    }
}

void GpuMemoryTracker::dump() {
    std::stringstream strout;
    dump(strout);
    ALOGD("%s", strout.str().c_str());
}

void GpuMemoryTracker::dump(std::ostream& stream) {
    for (int type = 0; type < NUM_TYPES; type++) {
        const TypeStats& stats = gObjectStats[type];
        stream << TYPE_NAMES[type];
        stream << " is using " << SizePrinter{stats.totalSize};
        stream << ", count = " << stats.count;
        stream << std::endl;
    }
}

int GpuMemoryTracker::getInstanceCount(GpuObjectType type) {
    return gObjectStats[static_cast<int>(type)].count;
}

int GpuMemoryTracker::getTotalSize(GpuObjectType type) {
    return gObjectStats[static_cast<int>(type)].totalSize;
}

void GpuMemoryTracker::onFrameCompleted() {
    if (ATRACE_ENABLED()) {
        char buf[128];
        for (int type = 0; type < NUM_TYPES; type++) {
            snprintf(buf, 128, "hwui_%s", TYPE_NAMES[type]);
            const TypeStats& stats = gObjectStats[type];
            ATRACE_INT(buf, stats.totalSize);
            snprintf(buf, 128, "hwui_%s_count", TYPE_NAMES[type]);
            ATRACE_INT(buf, stats.count);
        }
    }

    std::vector<const Texture*> freeList;
    for (const auto& obj : gObjectSet) {
        if (obj->objectType() == GpuObjectType::Texture) {
            const Texture* texture = static_cast<Texture*>(obj);
            if (texture->cleanup) {
                ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u",
                        texture->id(), texture->width(), texture->height());
                freeList.push_back(texture);
            }
        }
    }
    for (auto& texture : freeList) {
        const_cast<Texture*>(texture)->deleteTexture();
        delete texture;
    }
}

} // namespace uirenderer
} // namespace android;
