blob: ee9df7d51ec5addcfbcff1fff802cbe1c087a476 [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
Stephen Whited729e2d2019-08-28 12:37:47 -0400127void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels,
128 dawn::CommandEncoder copyEncoder) {
129 this->upload(texels, mipLevels, SkIRect::MakeWH(width(), height()), copyEncoder);
Stephen White0850dcd2019-08-13 15:28:47 -0400130}
131
Stephen Whited729e2d2019-08-28 12:37:47 -0400132void GrDawnTexture::upload(const GrMipLevel texels[], int mipLevels, const SkIRect& rect,
133 dawn::CommandEncoder copyEncoder) {
Stephen White0850dcd2019-08-13 15:28:47 -0400134 dawn::Device device = this->getDawnGpu()->device();
Stephen White0850dcd2019-08-13 15:28:47 -0400135
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 = width * GrBytesPerPixel(kRGBA_8888_GrPixelConfig);
157 origRowBytes = GrDawnRoundRowBytes(origRowBytes);
158 bitmap.allocPixels(info, origRowBytes);
159 bitmap.writePixels(srcPixmap);
160 if (!bitmap.peekPixels(&pixmap)) {
161 continue;
162 }
163 src = static_cast<const char*>(pixmap.addr());
164 } else {
165 src = static_cast<const char*>(texels[i].fPixels);
166 }
167 size_t rowBytes = GrDawnRoundRowBytes(origRowBytes);
168 size_t size = rowBytes * height;
169
170 dawn::BufferDescriptor desc;
171 desc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::CopySrc;
172 desc.size = size;
173
174 dawn::Buffer stagingBuffer = device.CreateBuffer(&desc);
175
176 if (rowBytes == origRowBytes) {
177 stagingBuffer.SetSubData(0, size,
178 static_cast<const uint8_t*>(static_cast<const void *>(src)));
179 } else {
180 char* buf = new char[size];
181 char* dst = buf;
182 for (uint32_t row = 0; row < height; row++) {
183 memcpy(dst, src, origRowBytes);
184 dst += rowBytes;
185 src += texels[i].fRowBytes;
186 }
187 stagingBuffer.SetSubData(0, size,
188 static_cast<const uint8_t*>(static_cast<const void*>(buf)));
189 delete[] buf;
190 }
191
192 dawn::BufferCopyView srcBuffer;
193 srcBuffer.buffer = stagingBuffer;
194 srcBuffer.offset = 0;
195 srcBuffer.rowPitch = rowBytes;
196 srcBuffer.imageHeight = height;
197
198 dawn::TextureCopyView dstTexture;
199 dstTexture.texture = fInfo.fTexture;
200 dstTexture.mipLevel = i;
201 dstTexture.origin = {x, y, 0};
202
203 dawn::Extent3D copySize = {width, height, 1};
Stephen Whited729e2d2019-08-28 12:37:47 -0400204 copyEncoder.CopyBufferToTexture(&srcBuffer, &dstTexture, &copySize);
Stephen White0850dcd2019-08-13 15:28:47 -0400205 x /= 2;
206 y /= 2;
207 width /= 2;
208 height /= 2;
209 }
210}