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