blob: 928c0b523d30c06d9adc3f8a5baa6541de946f3d [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;
Stephen White7fba36b2019-09-10 13:05:22 -0400169 GrDawnStagingBuffer* stagingBuffer = getDawnGpu()->getStagingBuffer(size);
Stephen White0850dcd2019-08-13 15:28:47 -0400170 if (rowBytes == origRowBytes) {
Stephen White7fba36b2019-09-10 13:05:22 -0400171 memcpy(stagingBuffer->fData, src, size);
Stephen White0850dcd2019-08-13 15:28:47 -0400172 } else {
Stephen White7fba36b2019-09-10 13:05:22 -0400173 char* dst = static_cast<char*>(stagingBuffer->fData);
Stephen White0850dcd2019-08-13 15:28:47 -0400174 for (uint32_t row = 0; row < height; row++) {
175 memcpy(dst, src, origRowBytes);
176 dst += rowBytes;
177 src += texels[i].fRowBytes;
178 }
Stephen White0850dcd2019-08-13 15:28:47 -0400179 }
Stephen White7fba36b2019-09-10 13:05:22 -0400180 dawn::Buffer buffer = stagingBuffer->fBuffer;
181 buffer.Unmap();
182 stagingBuffer->fData = nullptr;
Stephen White0850dcd2019-08-13 15:28:47 -0400183
184 dawn::BufferCopyView srcBuffer;
Stephen White7fba36b2019-09-10 13:05:22 -0400185 srcBuffer.buffer = buffer;
Stephen White0850dcd2019-08-13 15:28:47 -0400186 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};
Stephen Whited729e2d2019-08-28 12:37:47 -0400196 copyEncoder.CopyBufferToTexture(&srcBuffer, &dstTexture, &copySize);
Stephen White0850dcd2019-08-13 15:28:47 -0400197 x /= 2;
198 y /= 2;
199 width /= 2;
200 height /= 2;
201 }
202}