/*
 * Copyright 2016 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 straightforward test of using packed pixel configs (4444, 565).
 * This test will make sure that these RGBA_4444 and RGB_565 are always supported
 * as valid texturing configs.
 */

#include "tests/Test.h"

#include "include/gpu/GrDirectContext.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrTextureProxy.h"
#include "tools/gpu/ProxyUtils.h"

static const int DEV_W = 10, DEV_H = 10;
static const uint8_t TOL = 0x4;

static void check_component(skiatest::Reporter* reporter, uint8_t control, uint8_t test) {
    uint8_t diff = 0;
    if (control >= test) {
        diff = control - test;
    } else {
        diff = test - control;
    }
    REPORTER_ASSERT(reporter, diff < TOL);
}

static uint8_t expand_value(uint8_t original, int sigBits) {
    SkASSERT(sigBits >= 4);
    uint8_t inSigBitShift = 8 - sigBits;
    uint8_t duplBitShift = sigBits - inSigBitShift;
    return (original << inSigBitShift) + (original >> duplBitShift);
}

static void check_4444(skiatest::Reporter* reporter,
                       const SkTDArray<uint16_t>& controlData,
                       const SkTDArray<uint32_t>& readBuffer) {
    for (int j = 0; j < DEV_H; ++j) {
        for (int i = 0; i < DEV_W; ++i) {
            uint16_t control = controlData[i + j * DEV_H];
            uint32_t test = readBuffer[i + j * DEV_H];

            // Test alpha component
            uint8_t ctrlComp = expand_value(control & 0xF, 4);
            uint8_t testComp = GrColorUnpackA(test);
            check_component(reporter, ctrlComp, testComp);

            // Test blue component
            ctrlComp = expand_value((control >> 4) & 0xF, 4);
            testComp = GrColorUnpackB(test);
            check_component(reporter, ctrlComp, testComp);

            // Test green component
            ctrlComp = expand_value((control >> 8) & 0xF, 4);
            testComp = GrColorUnpackG(test);
            check_component(reporter, ctrlComp, testComp);

            // Test red component
            ctrlComp = expand_value((control >> 12) & 0xF, 4);
            testComp = GrColorUnpackR(test);
            check_component(reporter, ctrlComp, testComp);
        }
    }
}

static void check_565(skiatest::Reporter* reporter,
                      const SkTDArray<uint16_t>& controlData,
                      const SkTDArray<GrColor>& readBuffer) {
    for (int j = 0; j < DEV_H; ++j) {
        for (int i = 0; i < DEV_W; ++i) {
            uint16_t control = controlData[i + j * DEV_H];
            GrColor test = readBuffer[i + j * DEV_H];
            // Test blue component (5 bit control)
            uint8_t ctrlComp = expand_value(control & 0x1F, 5);
            uint8_t testComp = GrColorUnpackB(test);
            check_component(reporter, ctrlComp, testComp);

            // Test green component (6 bit control)
            ctrlComp = expand_value((control >> 5) & 0x3F, 6);
            testComp = GrColorUnpackG(test);
            check_component(reporter, ctrlComp, testComp);

            // Test red component (5 bit control)
            ctrlComp = expand_value((control >> 11) & 0x1F, 5);
            testComp = GrColorUnpackR(test);
            check_component(reporter, ctrlComp, testComp);
        }
    }
}

static void run_test(skiatest::Reporter* reporter, GrDirectContext* dContext, int arraySize,
                     SkColorType colorType) {
    SkTDArray<uint16_t> controlPixelData;
    // We will read back into an 8888 buffer since 565/4444 read backs aren't supported
    SkTDArray<GrColor> readBuffer;
    controlPixelData.setCount(arraySize);
    readBuffer.setCount(arraySize);

    for (int i = 0; i < arraySize; i += 2) {
        controlPixelData[i] = 0xF00F;
        controlPixelData[i + 1] = 0xA62F;
    }

    const SkImageInfo dstInfo =
            SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    for (auto origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) {
        auto grColorType = SkColorTypeToGrColorType(colorType);
        auto proxy = sk_gpu_test::MakeTextureProxyFromData(
                dContext, GrRenderable::kNo, origin,
                {grColorType, kPremul_SkAlphaType, nullptr, DEV_W, DEV_H},
                controlPixelData.begin(), 0);
        SkASSERT(proxy);

        GrSwizzle readSwizzle = dContext->priv().caps()->getReadSwizzle(proxy->backendFormat(),
                                                                        grColorType);

        GrSurfaceProxyView view(std::move(proxy), origin, readSwizzle);
        GrSurfaceContext sContext(dContext, std::move(view), grColorType, kPremul_SkAlphaType,
                                  nullptr);

        if (!sContext.readPixels(dContext, dstInfo, readBuffer.begin(), 0, {0, 0})) {
            // We only require this to succeed if the format is renderable.
            REPORTER_ASSERT(reporter, !dContext->colorTypeSupportedAsSurface(colorType));
            return;
        }

        if (kARGB_4444_SkColorType == colorType) {
            check_4444(reporter, controlPixelData, readBuffer);
        } else {
            SkASSERT(kRGB_565_SkColorType == colorType);
            check_565(reporter, controlPixelData, readBuffer);
        }
    }
}

static const int CONTROL_ARRAY_SIZE = DEV_W * DEV_H;

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(RGBA4444TextureTest, reporter, ctxInfo) {
    auto direct = ctxInfo.directContext();

    if (direct->colorTypeSupportedAsImage(kARGB_4444_SkColorType)) {
        run_test(reporter, direct, CONTROL_ARRAY_SIZE, kARGB_4444_SkColorType);
    }
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(RGB565TextureTest, reporter, ctxInfo) {
    auto direct = ctxInfo.directContext();

    if (direct->colorTypeSupportedAsImage(kRGB_565_SkColorType)) {
        run_test(reporter, direct, CONTROL_ARRAY_SIZE, kRGB_565_SkColorType);
    }
}
