xref: /aosp_15_r20/external/skia/src/gpu/ganesh/image/SkImage_RasterPinnable.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google LLC
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/ganesh/image/SkImage_RasterPinnable.h"
9 
10 #include "include/android/SkImageAndroid.h"
11 #include "include/core/SkBitmap.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkTypes.h"
16 #include "include/gpu/GpuTypes.h"
17 #include "include/gpu/ganesh/GrRecordingContext.h"
18 #include "src/core/SkImageInfoPriv.h"
19 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
20 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
21 #include "src/gpu/ganesh/SkGr.h"
22 #include "src/gpu/ganesh/image/GrImageUtils.h"
23 #include "src/image/SkImage_Base.h"
24 
25 #include <memory>
26 #include <tuple>
27 
asView(GrRecordingContext * rContext,skgpu::Mipmapped mipmapped,GrImageTexGenPolicy policy) const28 std::tuple<GrSurfaceProxyView, GrColorType> SkImage_RasterPinnable::asView(
29         GrRecordingContext* rContext,
30         skgpu::Mipmapped mipmapped,
31         GrImageTexGenPolicy policy) const {
32     if (fPinnedData) {
33         // We ignore the mipmap request here. If the pinned view isn't mipmapped then we will
34         // fallback to bilinear. The pin API is used by Android Framework which does not expose
35         // mipmapping. Moreover, we're moving towards requiring that images be made with mip levels
36         // if mipmapping is desired (skbug.com/10411)
37         mipmapped = skgpu::Mipmapped::kNo;
38         if (policy != GrImageTexGenPolicy::kDraw) {
39             return {skgpu::ganesh::CopyView(
40                             rContext,
41                             fPinnedData->fPinnedView,
42                             mipmapped,
43                             policy,
44                             /*label=*/"TextureForPinnableRasterImageWithPolicyNotEqualKDraw"),
45                     fPinnedData->fPinnedColorType};
46         }
47         return {fPinnedData->fPinnedView, fPinnedData->fPinnedColorType};
48     }
49     return skgpu::ganesh::RasterAsView(rContext, this, mipmapped, policy);
50 }
51 
52 namespace SkImages {
53 
PinnableRasterFromBitmap(const SkBitmap & bm)54 sk_sp<SkImage> PinnableRasterFromBitmap(const SkBitmap& bm) {
55     if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
56         return nullptr;
57     }
58 
59     return sk_make_sp<SkImage_RasterPinnable>(bm);
60 }
61 
62 }  // namespace SkImages
63 
64 namespace skgpu::ganesh {
65 
PinAsTexture(GrRecordingContext * rContext,SkImage * img)66 bool PinAsTexture(GrRecordingContext* rContext, SkImage* img) {
67     auto ib = as_IB(img);
68     if (ib->type() != SkImage_Base::Type::kRasterPinnable) {
69         // Cannot pin images which are not of subclass SkImage_RasterPinnable
70         return false;
71     }
72     auto raster = static_cast<SkImage_RasterPinnable*>(ib);
73     if (!raster->fPinnedData) {
74         auto data = std::make_unique<PinnedData>();
75         std::tie(data->fPinnedView, data->fPinnedColorType) =
76                 GrMakeCachedBitmapProxyView(rContext,
77                                             raster->bitmap(),
78                                             /*label=*/"ganesh_PinAsTexture",
79                                             skgpu::Mipmapped::kNo);
80         if (!data->fPinnedView) {
81             return false;
82         }
83         data->fPinnedUniqueID = raster->bitmap().getGenerationID();
84         data->fPinnedContextID = rContext->priv().contextID();
85         raster->fPinnedData.swap(data);
86     } else {
87         SkASSERT(raster->fPinnedData->fPinnedCount > 0);
88         SkASSERT(raster->fPinnedData->fPinnedUniqueID != 0);
89         if (rContext->priv().contextID() != raster->fPinnedData->fPinnedContextID) {
90             return false;
91         }
92     }
93     // Note: we only increment if the texture was successfully pinned
94     raster->fPinnedData->fPinnedCount++;
95     return true;
96 }
97 
UnpinTexture(GrRecordingContext *,SkImage * img)98 void UnpinTexture(GrRecordingContext*, SkImage* img) {
99     auto ib = as_IB(img);
100     if (ib->type() != SkImage_Base::Type::kRasterPinnable) {
101         // Cannot pin images which are not of subclass SkImage_RasterPinnable
102         return;
103     }
104     auto raster = static_cast<SkImage_RasterPinnable*>(ib);
105     if (!raster->fPinnedData) {
106         SkASSERT(false);
107         return;
108     }
109 
110     SkASSERT(raster->fPinnedData->fPinnedCount > 0);
111     SkASSERT(raster->fPinnedData->fPinnedUniqueID != 0);
112     // It would be good to check rContext->priv().contextID() != fPinnedContextID
113     // but Android used to (maybe still does) call Unpin with a freed context ptr
114 
115     raster->fPinnedData->fPinnedCount--;
116     if (raster->fPinnedData->fPinnedCount <= 0) {
117         raster->fPinnedData.reset(nullptr);
118     }
119 }
120 
121 }  // namespace skgpu::ganesh
122