/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Test.h"
// This is a GR test
#if SK_SUPPORT_GPU
#include "GrClipMaskManager.h"
#include "GrContextFactory.h"
#include "SkGpuDevice.h"

static const int X_SIZE = 12;
static const int Y_SIZE = 12;

////////////////////////////////////////////////////////////////////////////////
// note: this is unused
static GrTexture* createTexture(GrContext* context) {
    unsigned char textureData[X_SIZE][Y_SIZE][4];

    memset(textureData, 0, 4* X_SIZE * Y_SIZE);

    GrSurfaceDesc desc;

    // let Skia know we will be using this texture as a render target
    desc.fFlags     = kRenderTarget_GrSurfaceFlag;
    desc.fConfig    = kSkia8888_GrPixelConfig;
    desc.fWidth     = X_SIZE;
    desc.fHeight    = Y_SIZE;

    // We are initializing the texture with zeros here
    GrTexture* texture = context->createTexture(desc, false, textureData, 0);
    if (!texture) {
        return NULL;
    }

    return texture;
}

// Ensure that the 'getConservativeBounds' calls are returning bounds clamped
// to the render target
static void test_clip_bounds(skiatest::Reporter* reporter, GrContext* context) {

    static const int kXSize = 100;
    static const int kYSize = 100;

    GrSurfaceDesc desc;
    desc.fFlags     = kRenderTarget_GrSurfaceFlag;
    desc.fConfig    = kAlpha_8_GrPixelConfig;
    desc.fWidth     = kXSize;
    desc.fHeight    = kYSize;

    GrTexture* texture = context->createTexture(desc, false, NULL, 0);
    if (!texture) {
        return;
    }

    SkAutoTUnref<GrTexture> au(texture);

    SkIRect intScreen = SkIRect::MakeWH(kXSize, kYSize);
    SkRect screen;

    screen = SkRect::MakeWH(SkIntToScalar(kXSize),
                            SkIntToScalar(kYSize));

    SkRect clipRect(screen);
    clipRect.outset(10, 10);

    // create a clip stack that will (trivially) reduce to a single rect that
    // is larger than the screen
    SkClipStack stack;
    stack.clipDevRect(clipRect, SkRegion::kReplace_Op, false);

    bool isIntersectionOfRects = true;
    SkRect devStackBounds;

    stack.getConservativeBounds(0, 0, kXSize, kYSize,
                                &devStackBounds,
                                &isIntersectionOfRects);

    // make sure that the SkClipStack is behaving itself
    REPORTER_ASSERT(reporter, screen == devStackBounds);
    REPORTER_ASSERT(reporter, isIntersectionOfRects);

    // wrap the SkClipStack in a GrClipData
    GrClipData clipData;
    clipData.fClipStack.reset(SkRef(&stack));

    SkIRect devGrClipDataBound;
    clipData.getConservativeBounds(texture,
                                   &devGrClipDataBound,
                                   &isIntersectionOfRects);

    // make sure that GrClipData is behaving itself
    REPORTER_ASSERT(reporter, intScreen == devGrClipDataBound);
    REPORTER_ASSERT(reporter, isIntersectionOfRects);
}

////////////////////////////////////////////////////////////////////////////////
// verify that the top state of the stack matches the passed in state
static void check_state(skiatest::Reporter* reporter,
                        const GrClipMaskCache& cache,
                        const SkClipStack& clip,
                        GrTexture* mask,
                        const SkIRect& bound) {
    REPORTER_ASSERT(reporter, clip.getTopmostGenID() == cache.getLastClipGenID());

    REPORTER_ASSERT(reporter, mask == cache.getLastMask());

    SkIRect cacheBound;
    cache.getLastBound(&cacheBound);
    REPORTER_ASSERT(reporter, bound == cacheBound);
}

static void check_empty_state(skiatest::Reporter* reporter,
                              const GrClipMaskCache& cache) {
    REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID == cache.getLastClipGenID());
    REPORTER_ASSERT(reporter, NULL == cache.getLastMask());

    SkIRect emptyBound;
    emptyBound.setEmpty();

    SkIRect cacheBound;
    cache.getLastBound(&cacheBound);
    REPORTER_ASSERT(reporter, emptyBound == cacheBound);
}

////////////////////////////////////////////////////////////////////////////////
// basic test of the cache's base functionality:
//  push, pop, set, canReuse & getters
static void test_cache(skiatest::Reporter* reporter, GrContext* context) {

    if (false) { // avoid bit rot, suppress warning
        createTexture(context);
    }
    GrClipMaskCache cache;

    cache.setContext(context);

    // check initial state
    check_empty_state(reporter, cache);

    // set the current state
    SkIRect bound1;
    bound1.set(0, 0, 100, 100);

    SkClipStack clip1(bound1);

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = X_SIZE;
    desc.fHeight = Y_SIZE;
    desc.fConfig = kSkia8888_GrPixelConfig;

    cache.acquireMask(clip1.getTopmostGenID(), desc, bound1);

    GrTexture* texture1 = cache.getLastMask();
    REPORTER_ASSERT(reporter, texture1);
    if (NULL == texture1) {
        return;
    }

    // check that the set took
    check_state(reporter, cache, clip1, texture1, bound1);

    // push the state
    cache.push();

    // verify that the pushed state is initially empty
    check_empty_state(reporter, cache);

    // modify the new state
    SkIRect bound2;
    bound2.set(-10, -10, 10, 10);

    SkClipStack clip2(bound2);

    cache.acquireMask(clip2.getTopmostGenID(), desc, bound2);

    GrTexture* texture2 = cache.getLastMask();
    REPORTER_ASSERT(reporter, texture2);
    if (NULL == texture2) {
        return;
    }

    // check that the changes took
    check_state(reporter, cache, clip2, texture2, bound2);

    // check to make sure canReuse works
    REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2));
    REPORTER_ASSERT(reporter, !cache.canReuse(clip1.getTopmostGenID(), bound1));

    // pop the state
    cache.pop();

    // verify that the old state is restored
    check_state(reporter, cache, clip1, texture1, bound1);

    // manually clear the state
    cache.reset();

    // verify it is now empty
    check_empty_state(reporter, cache);

    // pop again - so there is no state
    cache.pop();

#if !defined(SK_DEBUG)
    // verify that the getters don't crash
    // only do in release since it generates asserts in debug
    check_empty_state(reporter, cache);
#endif
}

DEF_GPUTEST(ClipCache, reporter, factory) {
    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
        if (!GrContextFactory::IsRenderingGLContext(glType)) {
            continue;
        }
        GrContext* context = factory->get(glType);
        if (NULL == context) {
            continue;
        }

        test_cache(reporter, context);
        test_clip_bounds(reporter, context);
    }
}

#endif
