• 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 
get_image_info(GrRecordingContext * context,const SkBitmap & bitmap)20 static GrImageInfo get_image_info(GrRecordingContext* context, const SkBitmap& bitmap) {
21     GrColorType ct = SkColorTypeToGrColorType(bitmap.info().colorType());
22     GrBackendFormat format = context->priv().caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
23     if (!format.isValid()) {
24         ct = GrColorType::kRGBA_8888;
25     }
26     return {ct, bitmap.alphaType(), bitmap.refColorSpace(), bitmap.dimensions()};
27 }
28 
GrBitmapTextureMaker(GrRecordingContext * context,const SkBitmap & bitmap,Cached cached,SkBackingFit fit,bool useDecal)29 GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap,
30                                            Cached cached, SkBackingFit fit, bool useDecal)
31         : INHERITED(context, get_image_info(context, bitmap), useDecal)
32         , fBitmap(bitmap)
33         , fFit(fit) {
34     if (!bitmap.isVolatile() && cached == Cached::kYes) {
35         SkIPoint origin = bitmap.pixelRefOrigin();
36         SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
37                                            bitmap.height());
38         GrMakeKeyFromImageID(&fOriginalKey, bitmap.pixelRef()->getGenerationID(), subset);
39     }
40 }
41 
refOriginalTextureProxyView(bool willBeMipped,AllowedTexGenType onlyIfFast)42 GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(bool willBeMipped,
43                                                                      AllowedTexGenType onlyIfFast) {
44     if (AllowedTexGenType::kCheap == onlyIfFast) {
45         return {};
46     }
47 
48     GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
49     sk_sp<GrTextureProxy> proxy;
50     GrSwizzle swizzle;
51 
52     if (fOriginalKey.isValid()) {
53         auto colorType = SkColorTypeToGrColorType(fBitmap.colorType());
54         proxy = proxyProvider->findOrCreateProxyByUniqueKey(fOriginalKey, colorType);
55         if (proxy) {
56             swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
57                                                                      this->colorType());
58             if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
59                 return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
60             }
61         }
62     }
63 
64     if (!proxy) {
65         if (this->colorType() != SkColorTypeToGrColorType(fBitmap.info().colorType())) {
66             SkASSERT(this->colorType() == GrColorType::kRGBA_8888);
67             SkBitmap copy8888;
68             if (!copy8888.tryAllocPixels(fBitmap.info().makeColorType(kRGBA_8888_SkColorType)) ||
69                 !fBitmap.readPixels(copy8888.pixmap())) {
70                 return {};
71             }
72             copy8888.setImmutable();
73             proxy = proxyProvider->createProxyFromBitmap(
74                     copy8888, willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo, fFit);
75         } else {
76             proxy = proxyProvider->createProxyFromBitmap(
77                     fBitmap, willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo, fFit);
78         }
79         if (proxy) {
80             swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
81                                                                      this->colorType());
82             SkASSERT(!willBeMipped || GrMipMapped::kYes == proxy->mipMapped());
83             if (fOriginalKey.isValid()) {
84                 proxyProvider->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
85                 GrInstallBitmapUniqueKeyInvalidator(
86                         fOriginalKey, proxyProvider->contextID(), fBitmap.pixelRef());
87             }
88             return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
89         }
90     }
91 
92     if (proxy) {
93         SkASSERT(willBeMipped);
94         SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
95         SkASSERT(fOriginalKey.isValid());
96         // We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate
97         // a new mipped surface and copy the original proxy into the base layer. We will then let
98         // the gpu generate the rest of the mips.
99         GrColorType srcColorType = SkColorTypeToGrColorType(fBitmap.colorType());
100         auto mippedView = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(),
101                                                          kTopLeft_GrSurfaceOrigin, srcColorType);
102         if (auto mippedProxy = mippedView.asTextureProxy()) {
103             // In this case we are stealing the key from the original proxy which should only happen
104             // when we have just generated mipmaps for an originally unmipped proxy/texture. This
105             // means that all future uses of the key will access the mipmapped version. The texture
106             // backing the unmipped version will remain in the resource cache until the last texture
107             // proxy referencing it is deleted at which time it too will be deleted or recycled.
108             SkASSERT(proxy->getUniqueKey() == fOriginalKey);
109             SkASSERT(mippedView.origin() == kTopLeft_GrSurfaceOrigin);
110             SkASSERT(mippedView.swizzle() == swizzle);
111             proxyProvider->removeUniqueKeyFromProxy(proxy.get());
112             proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy);
113             GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextID(),
114                                                 fBitmap.pixelRef());
115             return mippedView;
116         }
117         // We failed to make a mipped proxy with the base copied into it. This could have
118         // been from failure to make the proxy or failure to do the copy. Thus we will fall
119         // back to just using the non mipped proxy; See skbug.com/7094.
120         return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
121     }
122     return {};
123 }
124 
makeCopyKey(const CopyParams & copyParams,GrUniqueKey * copyKey)125 void GrBitmapTextureMaker::makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) {
126     // Destination color space is irrelevant - we always upload the bitmap's contents as-is
127     if (fOriginalKey.isValid()) {
128         MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey);
129     }
130 }
131 
didCacheCopy(const GrUniqueKey & copyKey,uint32_t contextUniqueID)132 void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
133     GrInstallBitmapUniqueKeyInvalidator(copyKey, contextUniqueID, fBitmap.pixelRef());
134 }
135