• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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/graphite/TextureUtils.h"
9 
10 #include "include/core/SkBitmap.h"
11 #include "src/core/SkMipmap.h"
12 
13 #include "include/gpu/graphite/Context.h"
14 #include "include/gpu/graphite/GraphiteTypes.h"
15 #include "include/gpu/graphite/Recorder.h"
16 #include "include/gpu/graphite/Recording.h"
17 #include "src/gpu/graphite/Buffer.h"
18 #include "src/gpu/graphite/Caps.h"
19 #include "src/gpu/graphite/CommandBuffer.h"
20 #include "src/gpu/graphite/CopyTask.h"
21 #include "src/gpu/graphite/Image_Graphite.h"
22 #include "src/gpu/graphite/Log.h"
23 #include "src/gpu/graphite/RecorderPriv.h"
24 #include "src/gpu/graphite/ResourceProvider.h"
25 #include "src/gpu/graphite/SynchronizeToCpuTask.h"
26 #include "src/gpu/graphite/Texture.h"
27 #include "src/gpu/graphite/UploadTask.h"
28 
29 namespace skgpu::graphite {
30 
MakeBitmapProxyView(Recorder * recorder,const SkBitmap & bitmap,sk_sp<SkMipmap> mipmapsIn,Mipmapped mipmapped,skgpu::Budgeted budgeted)31 std::tuple<TextureProxyView, SkColorType> MakeBitmapProxyView(Recorder* recorder,
32                                                               const SkBitmap& bitmap,
33                                                               sk_sp<SkMipmap> mipmapsIn,
34                                                               Mipmapped mipmapped,
35                                                               skgpu::Budgeted budgeted) {
36     // Adjust params based on input and Caps
37     const skgpu::graphite::Caps* caps = recorder->priv().caps();
38     SkColorType ct = bitmap.info().colorType();
39 
40     if (bitmap.dimensions().area() <= 1) {
41         mipmapped = Mipmapped::kNo;
42     }
43 
44     auto textureInfo = caps->getDefaultSampledTextureInfo(ct, mipmapped, Protected::kNo,
45                                                           Renderable::kNo);
46     if (!textureInfo.isValid()) {
47         ct = kRGBA_8888_SkColorType;
48         textureInfo = caps->getDefaultSampledTextureInfo(ct, mipmapped, Protected::kNo,
49                                                          Renderable::kNo);
50     }
51     SkASSERT(textureInfo.isValid());
52 
53     // Convert bitmap to texture colortype if necessary
54     SkBitmap bmpToUpload;
55     if (ct != bitmap.info().colorType()) {
56         if (!bmpToUpload.tryAllocPixels(bitmap.info().makeColorType(ct)) ||
57             !bitmap.readPixels(bmpToUpload.pixmap())) {
58             return {};
59         }
60         bmpToUpload.setImmutable();
61     } else {
62         bmpToUpload = bitmap;
63     }
64 
65     if (!SkImageInfoIsValid(bmpToUpload.info())) {
66         return {};
67     }
68 
69     int mipLevelCount = (mipmapped == Mipmapped::kYes) ?
70             SkMipmap::ComputeLevelCount(bitmap.width(), bitmap.height()) + 1 : 1;
71 
72 
73     // setup MipLevels
74     sk_sp<SkMipmap> mipmaps;
75     std::vector<MipLevel> texels;
76     if (mipLevelCount == 1) {
77         texels.resize(mipLevelCount);
78         texels[0].fPixels = bmpToUpload.getPixels();
79         texels[0].fRowBytes = bmpToUpload.rowBytes();
80     } else {
81         mipmaps = SkToBool(mipmapsIn) ? mipmapsIn
82                                       : sk_ref_sp(SkMipmap::Build(bmpToUpload.pixmap(), nullptr));
83         if (!mipmaps) {
84             return {};
85         }
86 
87         SkASSERT(mipLevelCount == mipmaps->countLevels() + 1);
88         texels.resize(mipLevelCount);
89 
90         texels[0].fPixels = bmpToUpload.getPixels();
91         texels[0].fRowBytes = bmpToUpload.rowBytes();
92 
93         for (int i = 1; i < mipLevelCount; ++i) {
94             SkMipmap::Level generatedMipLevel;
95             mipmaps->getLevel(i - 1, &generatedMipLevel);
96             texels[i].fPixels = generatedMipLevel.fPixmap.addr();
97             texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
98             SkASSERT(texels[i].fPixels);
99             SkASSERT(generatedMipLevel.fPixmap.colorType() == bmpToUpload.colorType());
100         }
101     }
102 
103     // Create proxy
104     sk_sp<TextureProxy> proxy(new TextureProxy(bmpToUpload.dimensions(), textureInfo, budgeted));
105     if (!proxy) {
106         return {};
107     }
108     SkASSERT(caps->areColorTypeAndTextureInfoCompatible(ct, proxy->textureInfo()));
109     SkASSERT(mipmapped == Mipmapped::kNo || proxy->mipmapped() == Mipmapped::kYes);
110 
111     // Src and dst colorInfo are the same
112     const SkColorInfo& colorInfo = bmpToUpload.info().colorInfo();
113     // Add UploadTask to Recorder
114     UploadInstance upload = UploadInstance::Make(
115             recorder, proxy, colorInfo, colorInfo, texels,
116             SkIRect::MakeSize(bmpToUpload.dimensions()), nullptr);
117     if (!upload.isValid()) {
118         SKGPU_LOG_E("MakeBitmapProxyView: Could not create UploadInstance");
119         return {};
120     }
121     recorder->priv().add(UploadTask::Make(std::move(upload)));
122 
123     Swizzle swizzle = caps->getReadSwizzle(ct, textureInfo);
124     // If the color type is alpha-only, propagate the alpha value to the other channels.
125     if (colorInfo.colorType() == kAlpha_8_SkColorType) {
126         swizzle = Swizzle::Concat(swizzle, Swizzle("aaaa"));
127     }
128     return {{std::move(proxy), swizzle}, ct};
129 }
130 
MakeFromBitmap(Recorder * recorder,const SkColorInfo & colorInfo,const SkBitmap & bitmap,sk_sp<SkMipmap> mipmaps,skgpu::Budgeted budgeted,SkImage::RequiredImageProperties requiredProps)131 sk_sp<SkImage> MakeFromBitmap(Recorder* recorder,
132                               const SkColorInfo& colorInfo,
133                               const SkBitmap& bitmap,
134                               sk_sp<SkMipmap> mipmaps,
135                               skgpu::Budgeted budgeted,
136                               SkImage::RequiredImageProperties requiredProps) {
137     auto [ view, ct ] = MakeBitmapProxyView(recorder, bitmap, std::move(mipmaps),
138                                             requiredProps.fMipmapped, budgeted);
139     if (!view) {
140         return nullptr;
141     }
142 
143     SkASSERT(requiredProps.fMipmapped == skgpu::Mipmapped::kNo ||
144              view.proxy()->mipmapped() == skgpu::Mipmapped::kYes);
145     return sk_make_sp<skgpu::graphite::Image>(std::move(view),
146                                               colorInfo.makeColorType(ct));
147 }
148 
149 } // namespace skgpu::graphite
150