1 /*
2  * Copyright 2019 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/dawn/GrDawnTexture.h"
9 
10 #include "src/gpu/dawn/GrDawnGpu.h"
11 #include "src/gpu/dawn/GrDawnTextureRenderTarget.h"
12 #include "src/gpu/dawn/GrDawnUtil.h"
13 
GrDawnTexture(GrDawnGpu * gpu,const SkISize & size,GrPixelConfig config,dawn::TextureView textureView,const GrDawnImageInfo & info,GrMipMapsStatus mipMapsStatus)14 GrDawnTexture::GrDawnTexture(GrDawnGpu* gpu,
15                              const SkISize& size,
16                              GrPixelConfig config,
17                              dawn::TextureView textureView,
18                              const GrDawnImageInfo& info,
19                              GrMipMapsStatus mipMapsStatus)
20     : GrSurface(gpu, size, config, GrProtected::kNo)
21     , GrTexture(gpu, size, config, GrProtected::kNo, GrTextureType::k2D, mipMapsStatus)
22     , fInfo(info)
23     , fTextureView(textureView) {
24 }
25 
Make(GrDawnGpu * gpu,const SkISize & size,GrPixelConfig config,dawn::TextureFormat format,GrRenderable renderable,int sampleCnt,SkBudgeted budgeted,int mipLevels,GrMipMapsStatus status)26 sk_sp<GrDawnTexture> GrDawnTexture::Make(GrDawnGpu* gpu, const SkISize& size, GrPixelConfig config,
27                                          dawn::TextureFormat format, GrRenderable renderable,
28                                          int sampleCnt, SkBudgeted budgeted, int mipLevels,
29                                          GrMipMapsStatus status) {
30     bool renderTarget = renderable == GrRenderable::kYes;
31     dawn::TextureDescriptor textureDesc;
32 
33     textureDesc.usage =
34         dawn::TextureUsage::Sampled |
35         dawn::TextureUsage::CopySrc |
36         dawn::TextureUsage::CopyDst;
37 
38     if (renderTarget) {
39         textureDesc.usage |= dawn::TextureUsage::OutputAttachment;
40     }
41 
42     textureDesc.size.width = size.fWidth;
43     textureDesc.size.height = size.fHeight;
44     textureDesc.size.depth = 1;
45     textureDesc.format = format;
46     textureDesc.mipLevelCount = std::max(mipLevels, 1);
47     textureDesc.sampleCount = sampleCnt;
48 
49     dawn::Texture tex = gpu->device().CreateTexture(&textureDesc);
50 
51     if (!tex) {
52         return nullptr;
53     }
54 
55     dawn::TextureView textureView = tex.CreateView();
56 
57     if (!textureView) {
58         return nullptr;
59     }
60 
61     GrDawnImageInfo info;
62     info.fTexture = tex;
63     info.fFormat = textureDesc.format;
64     info.fLevelCount = mipLevels;
65     sk_sp<GrDawnTexture> result;
66     if (renderTarget) {
67         result = sk_sp<GrDawnTextureRenderTarget>(new GrDawnTextureRenderTarget(gpu,
68                                                                                 size,
69                                                                                 config,
70                                                                                 textureView,
71                                                                                 sampleCnt,
72                                                                                 info,
73                                                                                 status));
74     } else {
75         result = sk_sp<GrDawnTexture>(new GrDawnTexture(gpu, size, config, textureView, info,
76                                                         status));
77     }
78     result->registerWithCache(budgeted);
79     return result;
80 }
81 
backendFormat() const82 GrBackendFormat GrDawnTexture::backendFormat() const {
83     return GrBackendFormat::MakeDawn(fInfo.fFormat);
84 }
85 
MakeWrapped(GrDawnGpu * gpu,const SkISize & size,GrPixelConfig config,GrRenderable renderable,int sampleCnt,GrMipMapsStatus status,GrWrapCacheable cacheable,const GrDawnImageInfo & info)86 sk_sp<GrDawnTexture> GrDawnTexture::MakeWrapped(GrDawnGpu* gpu, const SkISize& size,
87                                                 GrPixelConfig config, GrRenderable renderable,
88                                                 int sampleCnt, GrMipMapsStatus status,
89                                                 GrWrapCacheable cacheable,
90                                                 const GrDawnImageInfo& info) {
91     dawn::TextureView textureView = info.fTexture.CreateView();
92     if (!textureView) {
93         return nullptr;
94     }
95 
96     sk_sp<GrDawnTexture> tex;
97     if (GrRenderable::kYes == renderable) {
98         tex = sk_sp<GrDawnTexture>(new GrDawnTextureRenderTarget(gpu, size, config, textureView,
99                                                                  sampleCnt, info, status));
100     } else {
101         tex = sk_sp<GrDawnTexture>(new GrDawnTexture(gpu, size, config, textureView, info, status));
102     }
103     tex->registerWithCacheWrapped(cacheable);
104     return tex;
105 }
106 
~GrDawnTexture()107 GrDawnTexture::~GrDawnTexture() {
108 }
109 
getDawnGpu() const110 GrDawnGpu* GrDawnTexture::getDawnGpu() const {
111     SkASSERT(!this->wasDestroyed());
112     return static_cast<GrDawnGpu*>(this->getGpu());
113 }
114 
onRelease()115 void GrDawnTexture::onRelease() {
116     INHERITED::onRelease();
117 }
118 
onAbandon()119 void GrDawnTexture::onAbandon() {
120     INHERITED::onAbandon();
121 }
122 
getBackendTexture() const123 GrBackendTexture GrDawnTexture::getBackendTexture() const {
124     return GrBackendTexture(this->width(), this->height(), fInfo);
125 }
126 
upload(const GrMipLevel texels[],int mipLevels,dawn::CommandEncoder copyEncoder)127 void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels,
128                            dawn::CommandEncoder copyEncoder) {
129     this->upload(texels, mipLevels, SkIRect::MakeWH(width(), height()), copyEncoder);
130 }
131 
upload(const GrMipLevel texels[],int mipLevels,const SkIRect & rect,dawn::CommandEncoder copyEncoder)132 void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels, const SkIRect& rect,
133                            dawn::CommandEncoder copyEncoder) {
134     dawn::Device device = this->getDawnGpu()->device();
135 
136     uint32_t x = rect.x();
137     uint32_t y = rect.y();
138     uint32_t width = rect.width();
139     uint32_t height = rect.height();
140 
141     for (int i = 0; i < mipLevels; i++) {
142         size_t origRowBytes = texels[i].fRowBytes;
143         SkBitmap bitmap;
144         SkPixmap pixmap;
145         const char* src;
146         if (kRGBA_4444_GrPixelConfig == this->config() ||
147             kRGB_565_GrPixelConfig == this->config() ||
148             kGray_8_GrPixelConfig == this->config()) {
149             SkImageInfo info;
150             info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
151             SkImageInfo srcInfo;
152             SkColorType colorType =
153                 GrColorTypeToSkColorType(GrPixelConfigToColorType(this->config()));
154             srcInfo = SkImageInfo::Make(width, height, colorType, kOpaque_SkAlphaType);
155             SkPixmap srcPixmap(srcInfo, texels[i].fPixels, origRowBytes);
156             origRowBytes = GrDawnRoundRowBytes(info.minRowBytes());
157             bitmap.allocPixels(info, origRowBytes);
158             bitmap.writePixels(srcPixmap);
159             if (!bitmap.peekPixels(&pixmap)) {
160                 continue;
161             }
162             src = static_cast<const char*>(pixmap.addr());
163         } else {
164             src = static_cast<const char*>(texels[i].fPixels);
165         }
166         size_t rowBytes = GrDawnRoundRowBytes(origRowBytes);
167         size_t size = rowBytes * height;
168         GrDawnStagingBuffer* stagingBuffer = getDawnGpu()->getStagingBuffer(size);
169         if (rowBytes == origRowBytes) {
170             memcpy(stagingBuffer->fData, src, size);
171         } else {
172             char* dst = static_cast<char*>(stagingBuffer->fData);
173             for (uint32_t row = 0; row < height; row++) {
174                 memcpy(dst, src, origRowBytes);
175                 dst += rowBytes;
176                 src += texels[i].fRowBytes;
177             }
178         }
179         dawn::Buffer buffer = stagingBuffer->fBuffer;
180         buffer.Unmap();
181         stagingBuffer->fData = nullptr;
182 
183         dawn::BufferCopyView srcBuffer;
184         srcBuffer.buffer = buffer;
185         srcBuffer.offset = 0;
186         srcBuffer.rowPitch = rowBytes;
187         srcBuffer.imageHeight = height;
188 
189         dawn::TextureCopyView dstTexture;
190         dstTexture.texture = fInfo.fTexture;
191         dstTexture.mipLevel = i;
192         dstTexture.origin = {x, y, 0};
193 
194         dawn::Extent3D copySize = {width, height, 1};
195         copyEncoder.CopyBufferToTexture(&srcBuffer, &dstTexture, &copySize);
196         x /= 2;
197         y /= 2;
198         width /= 2;
199         height /= 2;
200     }
201 }
202