/*
 * 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/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/mtl/GrMtlBackendContext.h"
#include "include/gpu/mtl/GrMtlTypes.h"
#include "src/core/SkMathPriv.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/image/SkImage_Base.h"
#include "tools/sk_app/MetalWindowContext.h"

using sk_app::DisplayParams;
using sk_app::MetalWindowContext;

namespace sk_app {

MetalWindowContext::MetalWindowContext(const DisplayParams& params)
        : WindowContext(params)
        , fValid(false)
        , fDrawableHandle(nil) {
    fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
}

NSURL* MetalWindowContext::CacheURL() {
    NSArray *paths = [[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory
                                                            inDomains:NSUserDomainMask];
    NSURL* cachePath = [paths objectAtIndex:0];
    return [cachePath URLByAppendingPathComponent:@"binaryArchive.metallib"];
}

void MetalWindowContext::initializeContext() {
    SkASSERT(!fContext);

    fDevice.reset(MTLCreateSystemDefaultDevice());
    fQueue.reset([*fDevice newCommandQueue]);

    if (fDisplayParams.fMSAASampleCount > 1) {
        if (@available(macOS 10.11, iOS 9.0, *)) {
            if (![*fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
                return;
            }
        } else {
            return;
        }
    }
    fSampleCount = fDisplayParams.fMSAASampleCount;
    fStencilBits = 8;

    fValid = this->onInitializeContext();

#if GR_METAL_SDK_VERSION >= 230
    if (fDisplayParams.fEnableBinaryArchive) {
        if (@available(macOS 11.0, iOS 14.0, *)) {
            sk_cfp<MTLBinaryArchiveDescriptor*> desc([MTLBinaryArchiveDescriptor new]);
            (*desc).url = CacheURL(); // try to load
            NSError* error;
            fPipelineArchive = [*fDevice newBinaryArchiveWithDescriptor:*desc error:&error];
            if (!fPipelineArchive) {
                (*desc).url = nil; // create new
                fPipelineArchive = [*fDevice newBinaryArchiveWithDescriptor:*desc error:&error];
                if (!fPipelineArchive) {
                    SkDebugf("Error creating MTLBinaryArchive:\n%s\n",
                             error.debugDescription.UTF8String);
                }
            }
        }
    } else {
        if (@available(macOS 11.0, iOS 14.0, *)) {
            fPipelineArchive = nil;
        }
    }
#endif

    GrMtlBackendContext backendContext = {};
    backendContext.fDevice.retain((GrMTLHandle)fDevice.get());
    backendContext.fQueue.retain((GrMTLHandle)fQueue.get());
#if GR_METAL_SDK_VERSION >= 230
    if (@available(macOS 11.0, iOS 14.0, *)) {
        backendContext.fBinaryArchive.retain((__bridge GrMTLHandle)fPipelineArchive);
    }
#endif
    fContext = GrDirectContext::MakeMetal(backendContext, fDisplayParams.fGrContextOptions);
    if (!fContext && fDisplayParams.fMSAASampleCount > 1) {
        fDisplayParams.fMSAASampleCount /= 2;
        this->initializeContext();
        return;
    }
}

void MetalWindowContext::destroyContext() {
    if (fContext) {
        // in case we have outstanding refs to this (lua?)
        fContext->abandonContext();
        fContext.reset();
    }

    this->onDestroyContext();

    fMetalLayer = nil;
    fValid = false;

#if GR_METAL_SDK_VERSION >= 230
    if (@available(macOS 11.0, iOS 14.0, *)) {
        [fPipelineArchive release];
    }
#endif
    fQueue.reset();
    fDevice.reset();
}

sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
    sk_sp<SkSurface> surface;
    if (fContext) {
        if (fDisplayParams.fDelayDrawableAcquisition) {
            surface = SkSurface::MakeFromCAMetalLayer(fContext.get(),
                                                      (__bridge GrMTLHandle)fMetalLayer,
                                                      kTopLeft_GrSurfaceOrigin, fSampleCount,
                                                      kBGRA_8888_SkColorType,
                                                      fDisplayParams.fColorSpace,
                                                      &fDisplayParams.fSurfaceProps,
                                                      &fDrawableHandle);
        } else {
            id<CAMetalDrawable> currentDrawable = [fMetalLayer nextDrawable];

            GrMtlTextureInfo fbInfo;
            fbInfo.fTexture.retain(currentDrawable.texture);

            GrBackendRenderTarget backendRT(fWidth,
                                            fHeight,
                                            fSampleCount,
                                            fbInfo);

            surface = SkSurface::MakeFromBackendRenderTarget(fContext.get(), backendRT,
                                                             kTopLeft_GrSurfaceOrigin,
                                                             kBGRA_8888_SkColorType,
                                                             fDisplayParams.fColorSpace,
                                                             &fDisplayParams.fSurfaceProps);

            fDrawableHandle = CFRetain((GrMTLHandle) currentDrawable);
        }
    }

    return surface;
}

void MetalWindowContext::swapBuffers() {
    id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;

    id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]);
    commandBuffer.label = @"Present";

    [commandBuffer presentDrawable:currentDrawable];
    [commandBuffer commit];
    // ARC is off in sk_app, so we need to release the CF ref manually
    CFRelease(fDrawableHandle);
    fDrawableHandle = nil;
}

void MetalWindowContext::setDisplayParams(const DisplayParams& params) {
    this->destroyContext();
    fDisplayParams = params;
    this->initializeContext();
}

void MetalWindowContext::activate(bool isActive) {
    // serialize pipeline archive
    if (!isActive) {
#if GR_METAL_SDK_VERSION >= 230
        if (@available(macOS 11.0, iOS 14.0, *)) {
            if (fPipelineArchive) {
                NSError* error;
                [fPipelineArchive serializeToURL:CacheURL() error:&error];
                if (error) {
                    SkDebugf("Error storing MTLBinaryArchive:\n%s\n",
                             error.debugDescription.UTF8String);
                }
            }
        }
#endif
    }
}

}   //namespace sk_app
