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, ©Size);
198 dawn::CommandBuffer copy = encoder.Finish();
199 queue.Submit(1, ©);
200
201 x /= 2;
202 y /= 2;
203 width /= 2;
204 height /= 2;
205 }
206 }
207