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

#include "tools/gpu/ManagedBackendTexture.h"

#include "include/core/SkBitmap.h"
#include "include/core/SkImageInfo.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/RefCntedCallback.h"

namespace {

struct Context {
    GrGpuFinishedProc fWrappedProc = nullptr;
    GrGpuFinishedContext fWrappedContext = nullptr;
    sk_sp<sk_gpu_test::ManagedBackendTexture> fMBETs[SkYUVAInfo::kMaxPlanes];
};

}  // anonymous namespace

namespace sk_gpu_test {

void ManagedBackendTexture::ReleaseProc(void* ctx) {
    std::unique_ptr<Context> context(static_cast<Context*>(ctx));
    if (context->fWrappedProc) {
        context->fWrappedProc(context->fWrappedContext);
    }
}

ManagedBackendTexture::~ManagedBackendTexture() {
    if (fDContext && fTexture.isValid()) {
        fDContext->deleteBackendTexture(fTexture);
    }
}

void* ManagedBackendTexture::releaseContext(GrGpuFinishedProc wrappedProc,
                                            GrGpuFinishedContext wrappedCtx) const {
    // Make sure we don't get a wrapped ctx without a wrapped proc
    SkASSERT(!wrappedCtx || wrappedProc);
    return new Context{wrappedProc, wrappedCtx, {sk_ref_sp(this)}};
}

void* ManagedBackendTexture::MakeYUVAReleaseContext(
        const sk_sp<ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes]) {
    auto context = new Context;
    for (int i = 0; i < SkYUVAInfo::kMaxPlanes; ++i) {
        context->fMBETs[i] = mbets[i];
    }
    return context;
}

sk_sp<skgpu::RefCntedCallback> ManagedBackendTexture::refCountedCallback() const {
    return skgpu::RefCntedCallback::Make(ReleaseProc, this->releaseContext());
}

void ManagedBackendTexture::wasAdopted() { fTexture = {}; }

sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromInfo(GrDirectContext* dContext,
                                                                 const SkImageInfo& ii,
                                                                 GrMipmapped mipmapped,
                                                                 GrRenderable renderable,
                                                                 GrProtected isProtected) {
    return MakeWithoutData(
            dContext, ii.width(), ii.height(), ii.colorType(), mipmapped, renderable, isProtected);
}

sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromBitmap(GrDirectContext* dContext,
                                                                   const SkBitmap& src,
                                                                   GrMipmapped mipmapped,
                                                                   GrRenderable renderable,
                                                                   GrProtected isProtected) {
    SkPixmap srcPixmap;
    if (!src.peekPixels(&srcPixmap)) {
        return nullptr;
    }

    return MakeFromPixmap(dContext, srcPixmap, mipmapped, renderable, isProtected);
}

sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromPixmap(GrDirectContext* dContext,
                                                                   const SkPixmap& src,
                                                                   GrMipmapped mipmapped,
                                                                   GrRenderable renderable,
                                                                   GrProtected isProtected) {
    std::vector<SkPixmap> levels({src});
    std::unique_ptr<SkMipmap> mm;

    if (mipmapped == GrMipmapped::kYes) {
        mm.reset(SkMipmap::Build(src, nullptr));
        if (!mm) {
            return nullptr;
        }
        for (int i = 0; i < mm->countLevels(); ++i) {
            SkMipmap::Level level;
            SkAssertResult(mm->getLevel(i, &level));
            levels.push_back(level.fPixmap);
        }
    }
    return MakeWithData(dContext,
                        levels.data(),
                        static_cast<int>(levels.size()),
                        kTopLeft_GrSurfaceOrigin,
                        renderable,
                        isProtected);
}

}  // namespace sk_gpu_test
