Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / graphite / UploadTask.cpp
1 /*
2  * Copyright 2022 Google LLC
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/graphite/UploadTask.h"
9
10 #include "include/gpu/graphite/Recorder.h"
11 #include "src/core/SkTraceEvent.h"
12 #include "src/gpu/graphite/Buffer.h"
13 #include "src/gpu/graphite/Caps.h"
14 #include "src/gpu/graphite/CommandBuffer.h"
15 #include "src/gpu/graphite/Log.h"
16 #include "src/gpu/graphite/RecorderPriv.h"
17 #include "src/gpu/graphite/ResourceProvider.h"
18 #include "src/gpu/graphite/Texture.h"
19 #include "src/gpu/graphite/TextureProxy.h"
20 #include "src/gpu/graphite/UploadBufferManager.h"
21
22 namespace skgpu::graphite {
23
24 UploadInstance::UploadInstance(const Buffer* buffer,
25                                sk_sp<TextureProxy> textureProxy,
26                                std::vector<BufferTextureCopyData> copyData)
27         : fBuffer(buffer), fTextureProxy(textureProxy), fCopyData(copyData) {}
28
29 size_t compute_combined_buffer_size(int mipLevelCount,
30                                     size_t bytesPerPixel,
31                                     size_t minTransferBufferAlignment,
32                                     const SkISize& baseDimensions,
33                                     SkTArray<size_t>* individualMipOffsets) {
34     SkASSERT(individualMipOffsets && !individualMipOffsets->count());
35     SkASSERT(mipLevelCount >= 1);
36
37     individualMipOffsets->push_back(0);
38
39     size_t combinedBufferSize = baseDimensions.width() * bytesPerPixel * baseDimensions.height();
40     SkISize levelDimensions = baseDimensions;
41
42     for (int currentMipLevel = 1; currentMipLevel < mipLevelCount; ++currentMipLevel) {
43         levelDimensions = {std::max(1, levelDimensions.width() /2),
44                            std::max(1, levelDimensions.height()/2)};
45
46         size_t trimmedSize = levelDimensions.area() * bytesPerPixel;
47         combinedBufferSize = SkAlignTo(combinedBufferSize, minTransferBufferAlignment);
48         SkASSERT((0 == combinedBufferSize % 4) && (0 == combinedBufferSize % bytesPerPixel));
49
50         individualMipOffsets->push_back(combinedBufferSize);
51         combinedBufferSize += trimmedSize;
52     }
53
54     SkASSERT(individualMipOffsets->count() == mipLevelCount);
55     return combinedBufferSize;
56 }
57
58 UploadInstance UploadInstance::Make(Recorder* recorder,
59                                     sk_sp<TextureProxy> textureProxy,
60                                     SkColorType dataColorType,
61                                     const std::vector<MipLevel>& levels,
62                                     const SkIRect& dstRect) {
63     const Caps* caps = recorder->priv().caps();
64     SkASSERT(caps->isTexturable(textureProxy->textureInfo()));
65
66     unsigned int mipLevelCount = levels.size();
67     // The assumption is either that we have no mipmaps, or that our rect is the entire texture
68     SkASSERT(mipLevelCount == 1 || dstRect == SkIRect::MakeSize(textureProxy->dimensions()));
69
70     // We assume that if the texture has mip levels, we either upload to all the levels or just the
71     // first.
72     SkASSERT(mipLevelCount == 1 || mipLevelCount == textureProxy->textureInfo().numMipLevels());
73
74     if (dstRect.isEmpty()) {
75         return {};
76     }
77
78     SkASSERT(caps->areColorTypeAndTextureInfoCompatible(dataColorType,
79                                                         textureProxy->textureInfo()));
80
81     if (mipLevelCount == 1 && !levels[0].fPixels) {
82         return {};   // no data to upload
83     }
84
85     for (unsigned int i = 0; i < mipLevelCount; ++i) {
86         // We do not allow any gaps in the mip data
87         if (!levels[i].fPixels) {
88             return {};
89         }
90     }
91
92     size_t bpp = SkColorTypeBytesPerPixel(dataColorType);
93     size_t minAlignment = caps->getTransferBufferAlignment(bpp);
94     SkTArray<size_t> individualMipOffsets(mipLevelCount);
95     size_t combinedBufferSize = compute_combined_buffer_size(mipLevelCount, bpp, minAlignment,
96                                                              dstRect.size(), &individualMipOffsets);
97     SkASSERT(combinedBufferSize);
98
99     UploadBufferManager* bufferMgr = recorder->priv().uploadBufferManager();
100     auto [writer, bufferInfo] = bufferMgr->getUploadWriter(combinedBufferSize, minAlignment);
101
102     std::vector<BufferTextureCopyData> copyData(mipLevelCount);
103
104     if (!bufferInfo.fBuffer) {
105         return {};
106     }
107     size_t baseOffset = bufferInfo.fOffset;
108
109     int currentWidth = dstRect.width();
110     int currentHeight = dstRect.height();
111     for (unsigned int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
112         const size_t trimRowBytes = currentWidth * bpp;
113         const size_t rowBytes = levels[currentMipLevel].fRowBytes;
114         const size_t mipOffset = individualMipOffsets[currentMipLevel];
115
116         // copy data into the buffer, skipping any trailing bytes
117         const char* src = (const char*)levels[currentMipLevel].fPixels;
118         writer.write(mipOffset, src, rowBytes, trimRowBytes, currentHeight);
119
120         copyData[currentMipLevel].fBufferOffset = baseOffset + mipOffset;
121         copyData[currentMipLevel].fBufferRowBytes = trimRowBytes;
122         copyData[currentMipLevel].fRect = {
123             dstRect.left(), dstRect.top(), // TODO: can we recompute this for mips?
124             dstRect.left() + currentWidth, dstRect.top() + currentHeight
125         };
126         copyData[currentMipLevel].fMipLevel = currentMipLevel;
127
128         currentWidth = std::max(1, currentWidth/2);
129         currentHeight = std::max(1, currentHeight/2);
130     }
131
132     ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%ux%u]",
133                              mipLevelCount > 1 ? "MipMap " : "",
134                              dstRect.width(), dstRect.height());
135
136     return {bufferInfo.fBuffer, std::move(textureProxy), std::move(copyData)};
137 }
138
139 void UploadInstance::addCommand(ResourceProvider* resourceProvider,
140                                 CommandBuffer* commandBuffer) const {
141     if (!fTextureProxy) {
142         SKGPU_LOG_E("No texture proxy specified for UploadTask");
143         return;
144     }
145     if (!fTextureProxy->instantiate(resourceProvider)) {
146         SKGPU_LOG_E("Could not instantiate texture proxy for UploadTask!");
147         return;
148     }
149
150     // The CommandBuffer doesn't take ownership of the upload buffer here; it's owned by
151     // UploadBufferManager, which will transfer ownership in transferToCommandBuffer.
152     commandBuffer->copyBufferToTexture(
153             fBuffer, fTextureProxy->refTexture(), fCopyData.data(), fCopyData.size());
154 }
155
156 //---------------------------------------------------------------------------
157
158 bool UploadList::recordUpload(Recorder* recorder,
159                               sk_sp<TextureProxy> textureProxy,
160                               SkColorType dataColorType,
161                               const std::vector<MipLevel>& levels,
162                               const SkIRect& dstRect) {
163     UploadInstance instance = UploadInstance::Make(recorder, std::move(textureProxy), dataColorType,
164                                                    levels, dstRect);
165     if (!instance.isValid()) {
166         return false;
167     }
168
169     fInstances.push_back(instance);
170     return true;
171 }
172
173 //---------------------------------------------------------------------------
174
175 sk_sp<UploadTask> UploadTask::Make(UploadList* uploadList) {
176     SkASSERT(uploadList && uploadList->fInstances.size() > 0);
177     return sk_sp<UploadTask>(new UploadTask(std::move(uploadList->fInstances)));
178 }
179
180 sk_sp<UploadTask> UploadTask::Make(const UploadInstance& instance) {
181     if (!instance.isValid()) {
182         return nullptr;
183     }
184     return sk_sp<UploadTask>(new UploadTask(instance));
185 }
186
187 UploadTask::UploadTask(std::vector<UploadInstance> instances) : fInstances(std::move(instances)) {}
188
189 UploadTask::UploadTask(const UploadInstance& instance) {
190     fInstances.push_back(instance);
191 }
192
193 UploadTask::~UploadTask() {}
194
195 bool UploadTask::addCommands(ResourceProvider* resourceProvider,
196                              CommandBuffer* commandBuffer) {
197     for (unsigned int i = 0; i < fInstances.size(); ++i) {
198         fInstances[i].addCommand(resourceProvider, commandBuffer);
199     }
200
201     return true;
202 }
203
204 } // namespace skgpu::graphite