/*
 * Copyright (C) 2017 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 <gtest/gtest.h>

#include "tests/common/TestUtils.h"
#include <GrRectanizer.h>
#include "pipeline/skia/VectorDrawableAtlas.h"

using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::skiapipeline;

RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, addGetRemove) {
    VectorDrawableAtlas atlas(100*100);
    atlas.prepareForDraw(renderThread.getGrContext());
    //create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
    const int MAX_RECTS = 150;
    AtlasEntry VDRects[MAX_RECTS];

    sk_sp<SkSurface> atlasSurface;

    //check we are able to allocate new rects
    //check that rects in the atlas do not intersect
    for (uint32_t i = 0; i < MAX_RECTS; i++) {
        VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
        if (0 == i) {
            atlasSurface = VDRects[0].surface;
        }
        ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
        ASSERT_TRUE(VDRects[i].surface.get() != nullptr);
        ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);

        //nothing in the atlas should intersect
        if (atlasSurface.get() == VDRects[i].surface.get()) {
            for (uint32_t j = 0; j < i; j++) {
                if (atlasSurface.get() == VDRects[j].surface.get()) {
                    ASSERT_FALSE(VDRects[i].rect.intersect(VDRects[j].rect));
                }
            }
        }
    }

    //first 1/3 rects should all be in the same surface
    for (uint32_t i = 1; i < MAX_RECTS/3; i++) {
        ASSERT_NE(VDRects[i].key, VDRects[0].key);
        ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
    }

    //first rect is using atlas and last is a standalone surface
    ASSERT_NE(VDRects[0].surface.get(), VDRects[MAX_RECTS-1].surface.get());

    //check getEntry returns the same surfaces that we had created
    for (uint32_t i = 0; i < MAX_RECTS; i++) {
        auto VDRect = atlas.getEntry(VDRects[i].key);
        ASSERT_TRUE(VDRect.key != INVALID_ATLAS_KEY);
        ASSERT_EQ(VDRects[i].key, VDRect.key);
        ASSERT_EQ(VDRects[i].surface.get(), VDRect.surface.get());
        ASSERT_EQ(VDRects[i].rect, VDRect.rect);
        atlas.releaseEntry(VDRect.key);
    }

    //check that any new rects will be allocated in the atlas, even that rectanizer is full.
    //rects in the atlas should not intersect.
    for (uint32_t i = 0; i < MAX_RECTS/3; i++) {
        VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
        ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
        ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
        ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);
        for (uint32_t j = 0; j < i; j++) {
            ASSERT_FALSE(VDRects[i].rect.intersect(VDRects[j].rect));
        }
    }
}


RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, disallowSharedSurface) {
    VectorDrawableAtlas atlas(100*100);
    //don't allow to use a shared surface
    atlas.setStorageMode(VectorDrawableAtlas::StorageMode::disallowSharedSurface);
    atlas.prepareForDraw(renderThread.getGrContext());
    //create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
    const int MAX_RECTS = 150;
    AtlasEntry VDRects[MAX_RECTS];

    //check we are able to allocate new rects
    //check that rects in the atlas use unique surfaces
    for (uint32_t i = 0; i < MAX_RECTS; i++) {
        VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
        ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
        ASSERT_TRUE(VDRects[i].surface.get() != nullptr);
        ASSERT_TRUE(VDRects[i].rect.width() == 10 && VDRects[i].rect.height() == 10);

        //nothing in the atlas should use the same surface
        for (uint32_t j = 0; j < i; j++) {
            ASSERT_NE(VDRects[i].surface.get(), VDRects[j].surface.get());
        }
    }
}

RENDERTHREAD_SKIA_PIPELINE_TEST(VectorDrawableAtlas, repack) {
    VectorDrawableAtlas atlas(100*100);
    ASSERT_FALSE(atlas.isFragmented());
    atlas.prepareForDraw(renderThread.getGrContext());
    ASSERT_FALSE(atlas.isFragmented());
    //create 150 rects 10x10, which won't fit in the atlas (atlas can fit no more than 100 rects)
    const int MAX_RECTS = 150;
    AtlasEntry VDRects[MAX_RECTS];

    sk_sp<SkSurface> atlasSurface;

    //fill the atlas with check we are able to allocate new rects
    for (uint32_t i = 0; i < MAX_RECTS; i++) {
        VDRects[i] = atlas.requestNewEntry(10, 10, renderThread.getGrContext());
        if (0 == i) {
            atlasSurface = VDRects[0].surface;
        }
        ASSERT_TRUE(VDRects[i].key != INVALID_ATLAS_KEY);
    }

    ASSERT_FALSE(atlas.isFragmented());

    //first 1/3 rects should all be in the same surface
    for (uint32_t i = 1; i < MAX_RECTS/3; i++) {
        ASSERT_NE(VDRects[i].key, VDRects[0].key);
        ASSERT_EQ(VDRects[i].surface.get(), atlasSurface.get());
    }

    //release all entries
    for (uint32_t i = 0; i < MAX_RECTS; i++) {
        auto VDRect = atlas.getEntry(VDRects[i].key);
        ASSERT_TRUE(VDRect.key != INVALID_ATLAS_KEY);
        atlas.releaseEntry(VDRect.key);
    }

    ASSERT_FALSE(atlas.isFragmented());

    //allocate 4x4 rects, which will fragment the atlas badly, because each entry occupies a 10x10
    //area
    for (uint32_t i = 0; i < 4*MAX_RECTS; i++) {
        AtlasEntry entry = atlas.requestNewEntry(4, 4, renderThread.getGrContext());
        ASSERT_TRUE(entry.key != INVALID_ATLAS_KEY);
    }

    ASSERT_TRUE(atlas.isFragmented());

    atlas.repackIfNeeded(renderThread.getGrContext());

    ASSERT_FALSE(atlas.isFragmented());
}