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

// This is a GPU-backend specific test. It relies on static intializers to work

#include "SkTypes.h"

#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_VULKAN)

#include "GrContextFactory.h"
#include "GrTest.h"
#include "Test.h"
#include "vk/GrVkGpu.h"


void fill_pixel_data(int width, int height, GrColor* data) {

    // build red-green gradient
    for (int j = 0; j < height; ++j) {
        for (int i = 0; i < width; ++i) {
            unsigned int red = (unsigned int)(256.f*(i / (float)width));
            unsigned int green = (unsigned int)(256.f*(j / (float)height));
            data[i + j*width] = GrColorPackRGBA(red - (red>>8), green - (green>>8), 0xff, 0xff);
        }
    }
}

bool does_full_buffer_contain_correct_color(GrColor* srcBuffer,
                                            GrColor* dstBuffer,
                                            GrPixelConfig config,
                                            int width,
                                            int height) {
    GrColor* srcPtr = srcBuffer;
    GrColor* dstPtr = dstBuffer;
    for (int j = 0; j < height; ++j) {
        for (int i = 0; i < width; ++i) {
            if (srcPtr[i] != dstPtr[i]) {
                return false;
            }
        }
        srcPtr += width;
        dstPtr += width;
    }
    return true;
}

void basic_texture_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config,
                        bool renderTarget, bool linearTiling) {
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());
    gpu->discard(NULL);

    const int kWidth = 16;
    const int kHeight = 16;
    SkAutoTMalloc<GrColor> srcBuffer(kWidth*kHeight);
    SkAutoTMalloc<GrColor> dstBuffer(kWidth*kHeight);

    fill_pixel_data(kWidth, kHeight, srcBuffer.get());

    const GrVkCaps* caps = reinterpret_cast<const GrVkCaps*>(context->caps());

    bool canCreate = true;
    // the expectation is that the given config is texturable/renderable with optimal tiling
    // but may not be with linear tiling
    if (linearTiling) {
        if (!caps->isConfigTexurableLinearly(config) ||
            (renderTarget && !caps->isConfigRenderableLinearly(config, false))) {
            canCreate = false;
        }
    }

    GrSurfaceDesc surfDesc;
    surfDesc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
    if (linearTiling) {
        surfDesc.fFlags |= kZeroCopy_GrSurfaceFlag;
    }
    surfDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
    surfDesc.fWidth = kWidth;
    surfDesc.fHeight = kHeight;
    surfDesc.fConfig = config;
    surfDesc.fSampleCnt = 0;
    GrTexture* tex0 = gpu->createTexture(surfDesc, SkBudgeted::kNo, srcBuffer, 0);
    if (tex0) {
        REPORTER_ASSERT(reporter, canCreate);
        gpu->readPixels(tex0, 0, 0, kWidth, kHeight, config, dstBuffer, 0);
        REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(srcBuffer,
                                                                         dstBuffer,
                                                                         config,
                                                                         kWidth,
                                                                         kHeight));

        tex0->writePixels(2, 10, 10, 2, config, srcBuffer);
        memset(dstBuffer, 0, kWidth*kHeight*sizeof(GrColor));
        gpu->readPixels(tex0, 2, 10, 10, 2, config, dstBuffer, 0);
        REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(srcBuffer,
                                                                         dstBuffer,
                                                                         config,
                                                                         10,
                                                                         2));

        tex0->unref();
    } else {
        REPORTER_ASSERT(reporter, !canCreate);
    }

    surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    GrTexture* tex1 = gpu->createTexture(surfDesc, SkBudgeted::kNo, srcBuffer, 0);
    if (tex1) {
        REPORTER_ASSERT(reporter, canCreate);
        gpu->readPixels(tex1, 0, 0, kWidth, kHeight, config, dstBuffer, 0);
        REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(srcBuffer,
                                                                         dstBuffer,
                                                                         config,
                                                                         kWidth,
                                                                         kHeight));

        tex1->writePixels(5, 4, 4, 5, config, srcBuffer);
        memset(dstBuffer, 0, kWidth*kHeight*sizeof(GrColor));
        gpu->readPixels(tex1, 5, 4, 4, 5, config, dstBuffer, 0);
        REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(srcBuffer,
                                                                         dstBuffer,
                                                                         config,
                                                                         4,
                                                                         5));

        tex1->unref();
    } else {
        REPORTER_ASSERT(reporter, !canCreate);
    }
}

DEF_GPUTEST(VkUploadPixelsTests, reporter, factory) {
    GrContextOptions opts;
    opts.fSuppressPrints = true;
    GrContextFactory debugFactory(opts);
    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
        if (static_cast<GrContextFactory::GLContextType>(type) !=
            GrContextFactory::kNative_GLContextType) {
            continue;
        }
        GrContext* context = debugFactory.get(static_cast<GrContextFactory::GLContextType>(type));
        if (context) {
            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, false, false);
            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, true, false);
            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, false, true);
            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, true, true);
            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, false, false);
            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, true, false);
            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, false, true);
            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, true, true);
        }

    }
}

#endif
