blob: 1fc6e0aeb6e8b550e00af928197a3b35a9078b92 [file] [log] [blame]
Stephen White0850dcd2019-08-13 15:28:47 -04001/*
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"
Stephen White9d421922019-08-14 15:07:42 -040011#include "src/gpu/dawn/GrDawnTextureRenderTarget.h"
Stephen White0850dcd2019-08-13 15:28:47 -040012#include "src/gpu/dawn/GrDawnUtil.h"
13
14GrDawnTexture::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
26sk_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) {
Stephen White9d421922019-08-14 15:07:42 -040067 result = sk_sp<GrDawnTextureRenderTarget>(new GrDawnTextureRenderTarget(gpu,
68 size,
69 config,
70 textureView,
71 sampleCnt,
72 info,
73 status));
Stephen White0850dcd2019-08-13 15:28:47 -040074 } 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
82GrBackendFormat GrDawnTexture::backendFormat() const {
83 return GrBackendFormat::MakeDawn(fInfo.fFormat);
84}
85
86sk_sp<GrDawnTexture> GrDawnTexture::MakeWrapped(GrDawnGpu* gpu, const SkISize& size,
Stephen White7a2930a2019-08-16 16:48:50 -040087 GrPixelConfig config, GrRenderable renderable,
88 int sampleCnt, GrMipMapsStatus status,
Stephen White0850dcd2019-08-13 15:28:47 -040089 GrWrapCacheable cacheable,
90 const GrDawnImageInfo& info) {
91 dawn::TextureView textureView = info.fTexture.CreateDefaultView();
92 if (!textureView) {
93 return nullptr;
94 }
95
Stephen White7a2930a2019-08-16 16:48:50 -040096 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 }
Stephen White0850dcd2019-08-13 15:28:47 -0400103 tex->registerWithCacheWrapped(cacheable);
104 return tex;
105}
106
107GrDawnTexture::~GrDawnTexture() {
108}
109
110GrDawnGpu* GrDawnTexture::getDawnGpu() const {
111 SkASSERT(!this->wasDestroyed());
112 return static_cast<GrDawnGpu*>(this->getGpu());
113}
114
115void GrDawnTexture::onRelease() {
116 INHERITED::onRelease();
117}
118
119void GrDawnTexture::onAbandon() {
120 INHERITED::onAbandon();
121}
122
123GrBackendTexture GrDawnTexture::getBackendTexture() const {
124 return GrBackendTexture(this->width(), this->height(), fInfo);
125}
126
127void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels) {
128 upload(texels, mipLevels, SkIRect::MakeWH(width(), height()));
129}
130
131void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels, const SkIRect& rect) {
132 dawn::Device device = this->getDawnGpu()->device();
133 dawn::Queue queue = this->getDawnGpu()->queue();
134
135 uint32_t x = rect.x();
136 uint32_t y = rect.y();
137 uint32_t width = rect.width();
138 uint32_t height = rect.height();
139
140 for (int i = 0; i < mipLevels; i++) {
141 size_t origRowBytes = texels[i].fRowBytes;
142 SkBitmap bitmap;
143 SkPixmap pixmap;
144 const char* src;
145 if (kRGBA_4444_GrPixelConfig == this->config() ||
146 kRGB_565_GrPixelConfig == this->config() ||
147 kGray_8_GrPixelConfig == this->config()) {
148 SkImageInfo info;
149 info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
150 SkImageInfo srcInfo;
151 SkColorType colorType =
152 GrColorTypeToSkColorType(GrPixelConfigToColorType(this->config()));
153 srcInfo = SkImageInfo::Make(width, height, colorType, kOpaque_SkAlphaType);
154 SkPixmap srcPixmap(srcInfo, texels[i].fPixels, origRowBytes);
155 origRowBytes = width * GrBytesPerPixel(kRGBA_8888_GrPixelConfig);
156 origRowBytes = GrDawnRoundRowBytes(origRowBytes);
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
169 dawn::BufferDescriptor desc;
170 desc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::CopySrc;
171 desc.size = size;
172
173 dawn::Buffer stagingBuffer = device.CreateBuffer(&desc);
174
175 if (rowBytes == origRowBytes) {
176 stagingBuffer.SetSubData(0, size,
177 static_cast<const uint8_t*>(static_cast<const void *>(src)));
178 } else {
179 char* buf = new char[size];
180 char* dst = buf;
181 for (uint32_t row = 0; row < height; row++) {
182 memcpy(dst, src, origRowBytes);
183 dst += rowBytes;
184 src += texels[i].fRowBytes;
185 }
186 stagingBuffer.SetSubData(0, size,
187 static_cast<const uint8_t*>(static_cast<const void*>(buf)));
188 delete[] buf;
189 }
190
191 dawn::BufferCopyView srcBuffer;
192 srcBuffer.buffer = stagingBuffer;
193 srcBuffer.offset = 0;
194 srcBuffer.rowPitch = rowBytes;
195 srcBuffer.imageHeight = height;
196
197 dawn::TextureCopyView dstTexture;
198 dstTexture.texture = fInfo.fTexture;
199 dstTexture.mipLevel = i;
200 dstTexture.origin = {x, y, 0};
201
202 dawn::Extent3D copySize = {width, height, 1};
203 dawn::CommandEncoder encoder = device.CreateCommandEncoder();
204 encoder.CopyBufferToTexture(&srcBuffer, &dstTexture, &copySize);
205 dawn::CommandBuffer copy = encoder.Finish();
206 queue.Submit(1, &copy);
207
208 x /= 2;
209 y /= 2;
210 width /= 2;
211 height /= 2;
212 }
213}