/*
 * 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/BackendTextureImageFactory.h"

#include "include/core/SkImage.h"
#include "include/core/SkPixmap.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContext.h"
#include "src/core/SkAutoPixmapStorage.h"

namespace {
class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> {
public:
    ~ManagedBackendTexture() {
        if (fContext && fTexture.isValid()) {
            fContext->submit(true);
            fContext->deleteBackendTexture(fTexture);
        }
    }

    static void Proc(void* context) { static_cast<ManagedBackendTexture*>(context)->unref(); }

    template <typename... Args>
    static sk_sp<ManagedBackendTexture> Make(GrContext* context, Args&&... args) {
        sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
        mbet->fContext = context;
        mbet->fTexture = context->createBackendTexture(std::forward<Args>(args)...,
                                                       Proc,
                                                       mbet->refAndPassAsContext());
        return mbet;
    }

    const GrBackendTexture& texture() { return fTexture; }

    void* refAndPassAsContext() {
        this->ref();
        return static_cast<void*>(this);
    }

private:
    ManagedBackendTexture() = default;
    GrContext* fContext = nullptr;
    GrBackendTexture fTexture;
};
}  // namespace

namespace sk_gpu_test {
sk_sp<SkImage> MakeBackendTextureImage(GrContext* context,
                                       const SkPixmap& pixmap,
                                       GrRenderable renderable,
                                       GrSurfaceOrigin origin) {
    const SkPixmap* src = &pixmap;
    SkAutoPixmapStorage temp;
    if (origin == kBottomLeft_GrSurfaceOrigin) {
        temp.alloc(src->info());
        auto s = static_cast<const char*>(src->addr(0, pixmap.height() - 1));
        auto d = static_cast<char*>(temp.writable_addr(0, 0));
        for (int y = 0; y < temp.height(); ++y, s -= pixmap.rowBytes(), d += temp.rowBytes()) {
            std::copy_n(s, temp.info().minRowBytes(), d);
        }
        src = &temp;
    }
    auto mbet = ManagedBackendTexture::Make(context, src, 1, renderable, GrProtected::kNo);
    auto image = SkImage::MakeFromTexture(context, mbet->texture(), origin, src->colorType(),
                                          src->alphaType(), src->refColorSpace(),
                                          ManagedBackendTexture::Proc, mbet->refAndPassAsContext());
    // We currently have an issue where depending on how MakeFromTexture fails it may not
    // call the release proc (to be fixed soon, crbug.com/1097484). For now we use this hack
    // to see if it failed without calling Proc.
    if (!image) {
        context->submit(true);
        if (!mbet->unique()) {
            ManagedBackendTexture::Proc(mbet.get());
        }
    }
    return image;
}
}  // namespace sk_gpu_test
