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

#include "include/core/SkSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
#include "tests/Test.h"

#import <Metal/Metal.h>
#import <MetalKit/MTKView.h>

#include "src/gpu/ganesh/mtl/GrMtlCaps.h"
#include "src/gpu/ganesh/mtl/GrMtlTextureRenderTarget.h"

DEF_GANESH_TEST_FOR_METAL_CONTEXT(MtlCopySurfaceTest, reporter, ctxInfo) {
    if (@available(macOS 11.0, iOS 9.0, *)) {
        static const int kWidth = 1024;
        static const int kHeight = 768;

        auto context = ctxInfo.directContext();

        // This is a bit weird, but it's the only way to get a framebufferOnly surface
        GrMtlGpu* gpu = (GrMtlGpu*) context->priv().getGpu();

        MTKView* view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, kWidth, kHeight)
                                                device:gpu->device()];
        id<CAMetalDrawable> drawable = [view currentDrawable];
        REPORTER_ASSERT(reporter, drawable.texture.framebufferOnly);
        REPORTER_ASSERT(reporter, drawable.texture.usage & MTLTextureUsageRenderTarget);

        // Test to see if we can initiate a copy via GrSurfaceProxys
        SkSurfaceProps props(0, kRGB_H_SkPixelGeometry);

        // TODO: check multisampled RT as well
        GrMtlTextureInfo fbInfo;
        fbInfo.fTexture.retain((__bridge const void*)(drawable.texture));
        GrBackendRenderTarget backendRT(kWidth, kHeight, fbInfo);

        GrProxyProvider* proxyProvider = context->priv().proxyProvider();
        sk_sp<GrSurfaceProxy> srcProxy = proxyProvider->wrapBackendRenderTarget(backendRT, nullptr);

        auto dstProxy = GrSurfaceProxy::Copy(context,
                                             srcProxy,
                                             kTopLeft_GrSurfaceOrigin,
                                             GrMipmapped::kNo,
                                             SkBackingFit::kExact,
                                             SkBudgeted::kYes,
                                             /*label=*/{});

        // TODO: GrSurfaceProxy::Copy doesn't check to see if the framebufferOnly bit is set yet.
        // Update this when it does -- it should fail.
        if (!dstProxy) {
            ERRORF(reporter, "Expected copy to succeed");
        }

        // Try direct copy via GPU (should fail)
        GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(drawable.texture.pixelFormat);
        GrSurface* src = srcProxy->peekSurface();
        sk_sp<GrTexture> dst =
                gpu->createTexture({kWidth, kHeight}, backendFormat, GrTextureType::k2D,
                                   GrRenderable::kNo, 1, GrMipmapped::kNo, SkBudgeted::kNo,
                                   GrProtected::kNo, /*label=*/"MtlCopySurfaceTest");

        bool result = gpu->copySurface(dst.get(), src, SkIRect::MakeXYWH(0, 0, kWidth, kHeight),
                                       SkIPoint::Make(0, 0));
        REPORTER_ASSERT(reporter, !result);
    }
}
