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, ©Size);
196 x /= 2;
197 y /= 2;
198 width /= 2;
199 height /= 2;
200 }
201 }
202