• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::TextureUsageBit::Sampled |
35         dawn::TextureUsageBit::CopySrc |
36         dawn::TextureUsageBit::CopyDst;
37 
38     if (renderTarget) {
39         textureDesc.usage |= dawn::TextureUsageBit::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.CreateDefaultView();
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,GrMipMapsStatus status,GrWrapCacheable cacheable,const GrDawnImageInfo & info)86 sk_sp<GrDawnTexture> GrDawnTexture::MakeWrapped(GrDawnGpu* gpu, const SkISize& size,
87                                                 GrPixelConfig config, GrMipMapsStatus status,
88                                                 GrWrapCacheable cacheable,
89                                                 const GrDawnImageInfo& info) {
90     dawn::TextureView textureView = info.fTexture.CreateDefaultView();
91     if (!textureView) {
92         return nullptr;
93     }
94 
95     sk_sp<GrDawnTexture> tex(new GrDawnTexture(gpu, size, config, textureView, info, status));
96     tex->registerWithCacheWrapped(cacheable);
97     return tex;
98 }
99 
~GrDawnTexture()100 GrDawnTexture::~GrDawnTexture() {
101 }
102 
getDawnGpu() const103 GrDawnGpu* GrDawnTexture::getDawnGpu() const {
104     SkASSERT(!this->wasDestroyed());
105     return static_cast<GrDawnGpu*>(this->getGpu());
106 }
107 
onRelease()108 void GrDawnTexture::onRelease() {
109     INHERITED::onRelease();
110 }
111 
onAbandon()112 void GrDawnTexture::onAbandon() {
113     INHERITED::onAbandon();
114 }
115 
getBackendTexture() const116 GrBackendTexture GrDawnTexture::getBackendTexture() const {
117     return GrBackendTexture(this->width(), this->height(), fInfo);
118 }
119 
upload(const GrMipLevel texels[],int mipLevels)120 void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels) {
121     upload(texels, mipLevels, SkIRect::MakeWH(width(), height()));
122 }
123 
upload(const GrMipLevel texels[],int mipLevels,const SkIRect & rect)124 void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels, const SkIRect& rect) {
125     dawn::Device device = this->getDawnGpu()->device();
126     dawn::Queue queue = this->getDawnGpu()->queue();
127 
128     uint32_t x = rect.x();
129     uint32_t y = rect.y();
130     uint32_t width = rect.width();
131     uint32_t height = rect.height();
132 
133     for (int i = 0; i < mipLevels; i++) {
134         size_t origRowBytes = texels[i].fRowBytes;
135         SkBitmap bitmap;
136         SkPixmap pixmap;
137         const char* src;
138         if (kRGBA_4444_GrPixelConfig == this->config() ||
139             kRGB_565_GrPixelConfig == this->config() ||
140             kGray_8_GrPixelConfig == this->config()) {
141             SkImageInfo info;
142             info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
143             SkImageInfo srcInfo;
144             SkColorType colorType =
145                 GrColorTypeToSkColorType(GrPixelConfigToColorType(this->config()));
146             srcInfo = SkImageInfo::Make(width, height, colorType, kOpaque_SkAlphaType);
147             SkPixmap srcPixmap(srcInfo, texels[i].fPixels, origRowBytes);
148             origRowBytes = width * GrBytesPerPixel(kRGBA_8888_GrPixelConfig);
149             origRowBytes = GrDawnRoundRowBytes(origRowBytes);
150             bitmap.allocPixels(info, origRowBytes);
151             bitmap.writePixels(srcPixmap);
152             if (!bitmap.peekPixels(&pixmap)) {
153                 continue;
154             }
155             src = static_cast<const char*>(pixmap.addr());
156         } else {
157             src = static_cast<const char*>(texels[i].fPixels);
158         }
159         size_t rowBytes = GrDawnRoundRowBytes(origRowBytes);
160         size_t size = rowBytes * height;
161 
162         dawn::BufferDescriptor desc;
163         desc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::CopySrc;
164         desc.size = size;
165 
166         dawn::Buffer stagingBuffer = device.CreateBuffer(&desc);
167 
168         if (rowBytes == origRowBytes) {
169             stagingBuffer.SetSubData(0, size,
170                 static_cast<const uint8_t*>(static_cast<const void *>(src)));
171         } else {
172             char* buf = new char[size];
173             char* dst = buf;
174             for (uint32_t row = 0; row < height; row++) {
175                 memcpy(dst, src, origRowBytes);
176                 dst += rowBytes;
177                 src += texels[i].fRowBytes;
178             }
179             stagingBuffer.SetSubData(0, size,
180                 static_cast<const uint8_t*>(static_cast<const void*>(buf)));
181             delete[] buf;
182         }
183 
184         dawn::BufferCopyView srcBuffer;
185         srcBuffer.buffer = stagingBuffer;
186         srcBuffer.offset = 0;
187         srcBuffer.rowPitch = rowBytes;
188         srcBuffer.imageHeight = height;
189 
190         dawn::TextureCopyView dstTexture;
191         dstTexture.texture = fInfo.fTexture;
192         dstTexture.mipLevel = i;
193         dstTexture.origin = {x, y, 0};
194 
195         dawn::Extent3D copySize = {width, height, 1};
196         dawn::CommandEncoder encoder = device.CreateCommandEncoder();
197         encoder.CopyBufferToTexture(&srcBuffer, &dstTexture, &copySize);
198         dawn::CommandBuffer copy = encoder.Finish();
199         queue.Submit(1, &copy);
200 
201         x /= 2;
202         y /= 2;
203         width /= 2;
204         height /= 2;
205     }
206 }
207