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 "GrBitmapTextureMaker.h"
9 
10 #include "GrGpuResourcePriv.h"
11 #include "GrProxyProvider.h"
12 #include "GrRecordingContext.h"
13 #include "GrRecordingContextPriv.h"
14 #include "GrSurfaceContext.h"
15 #include "SkBitmap.h"
16 #include "SkGr.h"
17 #include "SkMipMap.h"
18 #include "SkPixelRef.h"
19 
bmp_is_alpha_only(const SkBitmap & bm)20 static bool bmp_is_alpha_only(const SkBitmap& bm) { return kAlpha_8_SkColorType == bm.colorType(); }
21 
GrBitmapTextureMaker(GrRecordingContext * context,const SkBitmap & bitmap,bool useDecal)22 GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap,
23                                            bool useDecal)
24     : INHERITED(context, bitmap.width(), bitmap.height(), bmp_is_alpha_only(bitmap), useDecal)
25     , fBitmap(bitmap) {
26     if (!bitmap.isVolatile()) {
27         SkIPoint origin = bitmap.pixelRefOrigin();
28         SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
29                                            bitmap.height());
30         GrMakeKeyFromImageID(&fOriginalKey, bitmap.pixelRef()->getGenerationID(), subset);
31     }
32 }
33 
refOriginalTextureProxy(bool willBeMipped,AllowedTexGenType onlyIfFast)34 sk_sp<GrTextureProxy> GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeMipped,
35                                                                     AllowedTexGenType onlyIfFast) {
36     if (AllowedTexGenType::kCheap == onlyIfFast) {
37         return nullptr;
38     }
39 
40     GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
41     sk_sp<GrTextureProxy> proxy;
42 
43     if (fOriginalKey.isValid()) {
44         proxy = proxyProvider->findOrCreateProxyByUniqueKey(fOriginalKey, kTopLeft_GrSurfaceOrigin);
45         if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
46             return proxy;
47         }
48     }
49 
50     if (!proxy) {
51         if (willBeMipped) {
52             proxy = proxyProvider->createMipMapProxyFromBitmap(fBitmap);
53         }
54         if (!proxy) {
55             proxy = GrUploadBitmapToTextureProxy(proxyProvider, fBitmap);
56         }
57         if (proxy) {
58             if (fOriginalKey.isValid()) {
59                 proxyProvider->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
60             }
61             if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
62                 SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
63                 if (fOriginalKey.isValid()) {
64                     GrInstallBitmapUniqueKeyInvalidator(
65                             fOriginalKey, proxyProvider->contextID(), fBitmap.pixelRef());
66                 }
67                 return proxy;
68             }
69         }
70     }
71 
72     if (proxy) {
73         SkASSERT(willBeMipped);
74         SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
75         // We need a mipped proxy, but we either found a proxy earlier that wasn't mipped or
76         // generated a non mipped proxy. Thus we generate a new mipped surface and copy the original
77         // proxy into the base layer. We will then let the gpu generate the rest of the mips.
78         if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get())) {
79             SkASSERT(mippedProxy->origin() == kTopLeft_GrSurfaceOrigin);
80             if (fOriginalKey.isValid()) {
81                 // In this case we are stealing the key from the original proxy which should only
82                 // happen when we have just generated mipmaps for an originally unmipped
83                 // proxy/texture. This means that all future uses of the key will access the
84                 // mipmapped version. The texture backing the unmipped version will remain in the
85                 // resource cache until the last texture proxy referencing it is deleted at which
86                 // time it too will be deleted or recycled.
87                 SkASSERT(proxy->getUniqueKey() == fOriginalKey);
88                 proxyProvider->removeUniqueKeyFromProxy(proxy.get());
89                 proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy.get());
90                 GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextID(),
91                                                     fBitmap.pixelRef());
92             }
93             return mippedProxy;
94         }
95         // We failed to make a mipped proxy with the base copied into it. This could have
96         // been from failure to make the proxy or failure to do the copy. Thus we will fall
97         // back to just using the non mipped proxy; See skbug.com/7094.
98         return proxy;
99     }
100     return nullptr;
101 }
102 
makeCopyKey(const CopyParams & copyParams,GrUniqueKey * copyKey)103 void GrBitmapTextureMaker::makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) {
104     // Destination color space is irrelevant - we always upload the bitmap's contents as-is
105     if (fOriginalKey.isValid()) {
106         MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey);
107     }
108 }
109 
didCacheCopy(const GrUniqueKey & copyKey,uint32_t contextUniqueID)110 void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
111     GrInstallBitmapUniqueKeyInvalidator(copyKey, contextUniqueID, fBitmap.pixelRef());
112 }
113 
alphaType() const114 SkAlphaType GrBitmapTextureMaker::alphaType() const {
115     return fBitmap.alphaType();
116 }
117 
colorSpace() const118 SkColorSpace* GrBitmapTextureMaker::colorSpace() const {
119     return fBitmap.colorSpace();
120 }
121