1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkImage_GpuYUVA_DEFINED
9 #define SkImage_GpuYUVA_DEFINED
10 
11 #include "include/gpu/GrBackendSurface.h"
12 #include "include/gpu/GrContext.h"
13 #include "src/core/SkCachedData.h"
14 #include "src/image/SkImage_GpuBase.h"
15 
16 class GrTexture;
17 struct SkYUVASizeInfo;
18 
19 // Wraps the 3 or 4 planes of a YUVA image for consumption by the GPU.
20 // Initially any direct rendering will be done by passing the individual planes to a shader.
21 // Once any method requests a flattened image (e.g., onReadPixels), the flattened RGB
22 // proxy will be stored and used for any future rendering.
23 class SkImage_GpuYUVA : public SkImage_GpuBase {
24 public:
25     friend class GrYUVAImageTextureMaker;
26 
27     SkImage_GpuYUVA(sk_sp<GrContext>, int width, int height, uint32_t uniqueID, SkYUVColorSpace,
28                     sk_sp<GrTextureProxy> proxies[], GrColorType proxyColorTypes[], int numProxies,
29                     const SkYUVAIndex[4], GrSurfaceOrigin, sk_sp<SkColorSpace>);
30     ~SkImage_GpuYUVA() override;
31 
32     GrSemaphoresSubmitted onFlush(GrContext*, const GrFlushInfo&) override;
33 
34     // This returns the single backing proxy if the YUV channels have already been flattened but
35     // nullptr if they have not.
36     GrTextureProxy* peekProxy() const override;
37     sk_sp<GrTextureProxy> asTextureProxyRef(GrRecordingContext*) const override;
38 
onIsTextureBacked()39     virtual bool onIsTextureBacked() const override { return fProxies[0] || fRGBProxy; }
40 
41     sk_sp<SkImage> onMakeColorTypeAndColorSpace(GrRecordingContext*,
42                                                 SkColorType, sk_sp<SkColorSpace>) const final;
43 
44     sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const final;
45 
isYUVA()46     virtual bool isYUVA() const override { return true; }
47 
48     bool setupMipmapsForPlanes(GrRecordingContext*) const;
49 
50     // Returns a ref-ed texture proxy with miplevels
51     sk_sp<GrTextureProxy> asMippedTextureProxyRef(GrRecordingContext*) const;
52 
53 #if GR_TEST_UTILS
testingOnly_IsFlattened()54     bool testingOnly_IsFlattened() const {
55         // We should only have the flattened proxy or the planar proxies at one point in time.
56         SkASSERT(SkToBool(fRGBProxy) != SkToBool(fProxies[0]));
57         return SkToBool(fRGBProxy);
58     }
59 #endif
60 
61     /**
62      * This is the implementation of SkDeferredDisplayListRecorder::makeYUVAPromiseTexture.
63      */
64     static sk_sp<SkImage> MakePromiseYUVATexture(GrContext* context,
65                                                  SkYUVColorSpace yuvColorSpace,
66                                                  const GrBackendFormat yuvaFormats[],
67                                                  const SkISize yuvaSizes[],
68                                                  const SkYUVAIndex yuvaIndices[4],
69                                                  int width,
70                                                  int height,
71                                                  GrSurfaceOrigin imageOrigin,
72                                                  sk_sp<SkColorSpace> imageColorSpace,
73                                                  PromiseImageTextureFulfillProc textureFulfillProc,
74                                                  PromiseImageTextureReleaseProc textureReleaseProc,
75                                                  PromiseImageTextureDoneProc textureDoneProc,
76                                                  PromiseImageTextureContext textureContexts[],
77                                                  PromiseImageApiVersion);
78 
79 private:
80     SkImage_GpuYUVA(const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
81 
82     // This array will usually only be sparsely populated.
83     // The actual non-null fields are dictated by the 'fYUVAIndices' indices
84     mutable sk_sp<GrTextureProxy>    fProxies[4];
85     mutable GrColorType              fProxyColorTypes[4];
86     int                              fNumProxies;
87     SkYUVAIndex                      fYUVAIndices[4];
88     const SkYUVColorSpace            fYUVColorSpace;
89     GrSurfaceOrigin                  fOrigin;
90     // If this is non-null then the planar data should be converted from fFromColorSpace to
91     // this->colorSpace(). Otherwise we assume the planar data (post YUV->RGB conversion) is already
92     // in this->colorSpace().
93     const sk_sp<SkColorSpace> fFromColorSpace;
94 
95     // Repeated calls to onMakeColorSpace will result in a proliferation of unique IDs and
96     // SkImage_GpuYUVA instances. Cache the result of the last successful onMakeColorSpace call.
97     mutable sk_sp<SkColorSpace>      fOnMakeColorSpaceTarget;
98     mutable sk_sp<SkImage>           fOnMakeColorSpaceResult;
99 
100     // This is only allocated when the image needs to be flattened rather than
101     // using the separate YUVA planes. From thence forth we will only use the
102     // the RGBProxy.
103     mutable sk_sp<GrTextureProxy>    fRGBProxy;
104     typedef SkImage_GpuBase INHERITED;
105 };
106 
107 #endif
108