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

#include "SkTypes.h"

#include "GrGpu.h"
#include "GrContextPriv.h"
#include "GrTexture.h"
#include "SkConvertPixels.h"
#include "Test.h"
#include "TestUtils.h"

void testing_only_texture_test(skiatest::Reporter* reporter, GrContext* context, GrColorType ct,
                               bool renderTarget, bool doDataUpload, GrMipMapped mipMapped) {
    const int kWidth = 16;
    const int kHeight = 16;
    SkAutoTMalloc<GrColor> srcBuffer;
    if (doDataUpload) {
        srcBuffer.reset(kWidth * kHeight);
        fill_pixel_data(kWidth, kHeight, srcBuffer.get());
    }
    SkAutoTMalloc<GrColor> dstBuffer(kWidth * kHeight);

    GrGpu* gpu = context->contextPriv().getGpu();

    GrPixelConfig config = GrColorTypeToPixelConfig(ct, GrSRGBEncoded::kNo);
    if (!gpu->caps()->isConfigTexturable(config)) {
        return;
    }
    if (gpu->caps()->supportedReadPixelsColorType(config, ct) != ct) {
        return;
    }

    GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(srcBuffer,
                                                                       kWidth,
                                                                       kHeight,
                                                                       ct,
                                                                       renderTarget,
                                                                       mipMapped);
    if (!backendTex.isValid()) {
        return;
    }

    sk_sp<GrTexture> wrappedTex;
    if (renderTarget) {
        wrappedTex = gpu->wrapRenderableBackendTexture(
                backendTex, 1, GrWrapOwnership::kAdopt_GrWrapOwnership, GrWrapCacheable::kNo);
    } else {
        wrappedTex = gpu->wrapBackendTexture(backendTex, GrWrapOwnership::kAdopt_GrWrapOwnership,
                                             GrWrapCacheable::kNo, kRead_GrIOType);
    }
    REPORTER_ASSERT(reporter, wrappedTex);

    int rowBytes = GrColorTypeBytesPerPixel(ct) * kWidth;
    bool result = gpu->readPixels(wrappedTex.get(), 0, 0, kWidth,
                                  kHeight, ct, dstBuffer, rowBytes);

    if (!doDataUpload) {
        // createTestingOnlyBackendTexture will fill the texture with 0's if no data is provided, so
        // we set the expected result likewise.
        srcBuffer.reset(kWidth * kHeight);
        memset(srcBuffer, 0, kWidth * kHeight * sizeof(GrColor));
    }
    REPORTER_ASSERT(reporter, result);
    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(srcBuffer, dstBuffer,
                                                                     kWidth, kHeight));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTestingBackendTextureUploadTest, reporter, ctxInfo) {
    for (auto colorType: { GrColorType::kRGBA_8888, GrColorType::kBGRA_8888 }) {
        for (bool renderable: {true, false}) {
            for (bool doDataUpload: {true, false}) {
                testing_only_texture_test(reporter, ctxInfo.grContext(), colorType,
                                          renderable, doDataUpload, GrMipMapped::kNo);

                if (!doDataUpload) {
                    testing_only_texture_test(reporter, ctxInfo.grContext(), colorType,
                                              renderable, doDataUpload, GrMipMapped::kYes);
                }
            }
        }
    }
}

