1 /*
2  * Copyright 2016 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 #include "src/gpu/GrImageTextureMaker.h"
9 
10 #include "src/gpu/GrColorSpaceXform.h"
11 #include "src/gpu/SkGr.h"
12 #include "src/gpu/effects/GrYUVtoRGBEffect.h"
13 #include "src/image/SkImage_GpuYUVA.h"
14 #include "src/image/SkImage_Lazy.h"
15 
GrImageTextureMaker(GrRecordingContext * context,const SkImage * client,SkImage::CachingHint chint,bool useDecal)16 GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context, const SkImage* client,
17                                          SkImage::CachingHint chint, bool useDecal)
18         : INHERITED(context, client->width(), client->height(), client->imageInfo().colorInfo(),
19                     useDecal)
20         , fImage(static_cast<const SkImage_Lazy*>(client))
21         , fCachingHint(chint) {
22     SkASSERT(client->isLazyGenerated());
23     GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(),
24                          SkIRect::MakeWH(this->width(), this->height()));
25 }
26 
refOriginalTextureProxy(bool willBeMipped,AllowedTexGenType onlyIfFast)27 sk_sp<GrTextureProxy> GrImageTextureMaker::refOriginalTextureProxy(bool willBeMipped,
28                                                                    AllowedTexGenType onlyIfFast) {
29     return fImage->lockTextureProxy(this->context(), fOriginalKey, fCachingHint,
30                                     willBeMipped, onlyIfFast);
31 }
32 
makeCopyKey(const CopyParams & stretch,GrUniqueKey * paramsCopyKey)33 void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
34     if (fOriginalKey.isValid() && SkImage::kAllow_CachingHint == fCachingHint) {
35         GrUniqueKey cacheKey;
36         fImage->makeCacheKeyFromOrigKey(fOriginalKey, &cacheKey);
37         MakeCopyKeyFromOrigKey(cacheKey, stretch, paramsCopyKey);
38     }
39 }
40 
41 
42 /////////////////////////////////////////////////////////////////////////////////////////////////
43 
GrYUVAImageTextureMaker(GrContext * context,const SkImage * client,bool useDecal)44 GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client,
45                                                  bool useDecal)
46         : INHERITED(context, client->width(), client->height(), client->imageInfo().colorInfo(),
47                     useDecal)
48         , fImage(static_cast<const SkImage_GpuYUVA*>(client)) {
49     SkASSERT(as_IB(client)->isYUVA());
50     GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(),
51                          SkIRect::MakeWH(this->width(), this->height()));
52 }
53 
refOriginalTextureProxy(bool willBeMipped,AllowedTexGenType onlyIfFast)54 sk_sp<GrTextureProxy> GrYUVAImageTextureMaker::refOriginalTextureProxy(bool willBeMipped,
55                                                                    AllowedTexGenType onlyIfFast) {
56     if (AllowedTexGenType::kCheap == onlyIfFast) {
57         return nullptr;
58     }
59 
60     if (willBeMipped) {
61         return fImage->asMippedTextureProxyRef(this->context());
62     } else {
63         return fImage->asTextureProxyRef(this->context());
64     }
65 }
66 
makeCopyKey(const CopyParams & stretch,GrUniqueKey * paramsCopyKey)67 void GrYUVAImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
68     // TODO: Do we ever want to disable caching?
69     if (fOriginalKey.isValid()) {
70         GrUniqueKey cacheKey;
71         static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
72         GrUniqueKey::Builder builder(&cacheKey, fOriginalKey, kDomain, 0, "Image");
73         MakeCopyKeyFromOrigKey(cacheKey, stretch, paramsCopyKey);
74     }
75 }
76 
createFragmentProcessor(const SkMatrix & textureMatrix,const SkRect & constraintRect,FilterConstraint filterConstraint,bool coordsLimitedToConstraintRect,const GrSamplerState::Filter * filterOrNullForBicubic)77 std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProcessor(
78     const SkMatrix& textureMatrix,
79     const SkRect& constraintRect,
80     FilterConstraint filterConstraint,
81     bool coordsLimitedToConstraintRect,
82     const GrSamplerState::Filter* filterOrNullForBicubic) {
83 
84     // Check simple cases to see if we need to fall back to flattening the image (or whether it's
85     // already been flattened.)
86     if (!filterOrNullForBicubic || this->domainNeedsDecal() || fImage->fRGBProxy) {
87         return this->INHERITED::createFragmentProcessor(textureMatrix, constraintRect,
88                                                         filterConstraint,
89                                                         coordsLimitedToConstraintRect,
90                                                         filterOrNullForBicubic);
91     }
92 
93     // Check to see if the client has given us pre-mipped textures or we can generate them
94     // If not, fall back to bilerp. Also fall back to bilerp when a domain is requested
95     GrSamplerState::Filter filter = *filterOrNullForBicubic;
96     if (GrSamplerState::Filter::kMipMap == filter &&
97         (filterConstraint == GrTextureProducer::kYes_FilterConstraint ||
98          !fImage->setupMipmapsForPlanes(this->context()))) {
99         filter = GrSamplerState::Filter::kBilerp;
100     }
101 
102     // Cannot rely on GrTextureProducer's domain infrastructure since we need to calculate domain's
103     // per plane, which may be different, so respect the filterConstraint without any additional
104     // analysis.
105     const SkRect* domain = nullptr;
106     if (filterConstraint == GrTextureProducer::kYes_FilterConstraint) {
107         domain = &constraintRect;
108     }
109 
110     auto fp = GrYUVtoRGBEffect::Make(fImage->fProxies, fImage->fYUVAIndices,
111                                      fImage->fYUVColorSpace, filter, textureMatrix, domain);
112     if (fImage->fFromColorSpace) {
113         fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->fFromColorSpace.get(),
114                                            fImage->alphaType(), fImage->colorSpace());
115     }
116     return fp;
117 }
118