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

#ifndef SkImage_GpuYUVA_DEFINED
#define SkImage_GpuYUVA_DEFINED

#include "GrBackendSurface.h"
#include "GrContext.h"
#include "SkCachedData.h"
#include "SkImage_GpuBase.h"

class GrTexture;
struct SkYUVASizeInfo;

// Wraps the 3 or 4 planes of a YUVA image for consumption by the GPU.
// Initially any direct rendering will be done by passing the individual planes to a shader.
// Once any method requests a flattened image (e.g., onReadPixels), the flattened RGB
// proxy will be stored and used for any future rendering.
class SkImage_GpuYUVA : public SkImage_GpuBase {
public:
    friend class GrYUVAImageTextureMaker;

    SkImage_GpuYUVA(sk_sp<GrContext>, int width, int height, uint32_t uniqueID, SkYUVColorSpace,
                    sk_sp<GrTextureProxy> proxies[], int numProxies, const SkYUVAIndex[4],
                    GrSurfaceOrigin, sk_sp<SkColorSpace>);
    ~SkImage_GpuYUVA() override;

    SkImageInfo onImageInfo() const override;

    GrTextureProxy* peekProxy() const override { return this->asTextureProxyRef().get(); }
    sk_sp<GrTextureProxy> asTextureProxyRef() const override;

    virtual bool onIsTextureBacked() const override { return SkToBool(fProxies[0].get()); }

    sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const final;

    virtual bool isYUVA() const override { return true; }
    virtual bool asYUVATextureProxiesRef(sk_sp<GrTextureProxy> proxies[4],
                                         SkYUVAIndex yuvaIndices[4],
                                         SkYUVColorSpace* yuvColorSpace) const override {
        for (int i = 0; i < 4; ++i) {
            proxies[i] = fProxies[i];
            yuvaIndices[i] = fYUVAIndices[i];
        }
        *yuvColorSpace = fYUVColorSpace;
        return true;
    }

    bool setupMipmapsForPlanes() const;

    // Returns a ref-ed texture proxy with miplevels
    sk_sp<GrTextureProxy> asMippedTextureProxyRef() const;

    SkColorSpace* targetColorSpace() const { return fTargetColorSpace.get(); }

    /**
        Create a new SkImage_GpuYUVA that's very similar to SkImage created by MakeFromYUVATextures.
        The main difference is that the client doesn't have the backend textures on the gpu yet but
        they know all the properties of the texture. So instead of passing in GrBackendTextures the
        client supplies GrBackendFormats and the image size.

        When we actually send the draw calls to the GPU, we will call the textureFulfillProc and
        the client will return the GrBackendTextures to us. The properties of the GrBackendTextures
        must match those set during the SkImage creation, and it must have valid backend gpu
        textures. The gpu textures supplied by the client must stay valid until we call the
        textureReleaseProc.

        When we are done with the texture returned by the textureFulfillProc we will call the
        textureReleaseProc passing in the textureContext. This is a signal to the client that they
        are free to delete the underlying gpu textures. If future draws also use the same promise
        image we will call the textureFulfillProc again if we've already called the
        textureReleaseProc. We will always call textureFulfillProc and textureReleaseProc in pairs.
        In other words we will never call textureFulfillProc or textureReleaseProc multiple times
        for the same textureContext before calling the other.

        We call the promiseDoneProc when we will no longer call the textureFulfillProc again. We
        also guarantee that there will be no outstanding textureReleaseProcs that still need to be
        called when we call the textureDoneProc. Thus when the textureDoneProc gets called the
        client is able to cleanup all GPU objects and meta data needed for the textureFulfill call.

        @param context             Gpu context
        @param yuvColorSpace       color range of expected YUV pixels
        @param yuvaFormats         formats of promised gpu textures for each YUVA plane
        @param yuvaSizes           width and height of promised gpu textures
        @param yuvaIndices         mapping from yuv plane index to texture representing that plane
        @param width               width of promised gpu texture
        @param height              height of promised gpu texture
        @param imageOrigin         one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
        @param imageColorSpace     range of colors; may be nullptr
        @param textureFulfillProc  function called to get actual gpu texture
        @param textureReleaseProc  function called when texture can be released
        @param textureDoneProc     function called when we will no longer call textureFulfillProc
        @param textureContexts     per-texture state passed to textureFulfillProc,
                                   textureReleaseProc, and textureDoneProc
        @return                    created SkImage, or nullptr
     */
    static sk_sp<SkImage> MakePromiseYUVATexture(GrContext* context,
                                                 SkYUVColorSpace yuvColorSpace,
                                                 const GrBackendFormat yuvaFormats[],
                                                 const SkISize yuvaSizes[],
                                                 const SkYUVAIndex yuvaIndices[4],
                                                 int width,
                                                 int height,
                                                 GrSurfaceOrigin imageOrigin,
                                                 sk_sp<SkColorSpace> imageColorSpace,
                                                 PromiseImageTextureFulfillProc textureFulfillProc,
                                                 PromiseImageTextureReleaseProc textureReleaseProc,
                                                 PromiseImageTextureDoneProc textureDoneProc,
                                                 PromiseImageTextureContext textureContexts[]);

private:
    SkImage_GpuYUVA(const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);

    // This array will usually only be sparsely populated.
    // The actual non-null fields are dictated by the 'fYUVAIndices' indices
    mutable sk_sp<GrTextureProxy>    fProxies[4];
    int                              fNumProxies;
    SkYUVAIndex                      fYUVAIndices[4];
    const SkYUVColorSpace            fYUVColorSpace;
    GrSurfaceOrigin                  fOrigin;
    const sk_sp<SkColorSpace>        fTargetColorSpace;

    // Repeated calls to onMakeColorSpace will result in a proliferation of unique IDs and
    // SkImage_GpuYUVA instances. Cache the result of the last successful onMakeColorSpace call.
    mutable sk_sp<SkColorSpace>      fOnMakeColorSpaceTarget;
    mutable sk_sp<SkImage>           fOnMakeColorSpaceResult;

    // This is only allocated when the image needs to be flattened rather than
    // using the separate YUVA planes. From thence forth we will only use the
    // the RGBProxy.
    mutable sk_sp<GrTextureProxy>    fRGBProxy;
    typedef SkImage_GpuBase INHERITED;
};

#endif
