Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
UploadTask.cpp
Go to the documentation of this file.
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
9
15#include "src/core/SkMipmap.h"
17#include "src/gpu/DataUtils.h"
27
28using namespace skia_private;
29
30namespace skgpu::graphite {
31
32UploadInstance::UploadInstance() = default;
33UploadInstance::UploadInstance(UploadInstance&&) = default;
34UploadInstance& UploadInstance::operator=(UploadInstance&&) = default;
36
37UploadInstance::UploadInstance(const Buffer* buffer,
38 size_t bytesPerPixel,
39 sk_sp<TextureProxy> textureProxy,
40 std::unique_ptr<ConditionalUploadContext> condContext)
41 : fBuffer(buffer)
42 , fBytesPerPixel(bytesPerPixel)
43 , fTextureProxy(textureProxy)
44 , fConditionalContext(std::move(condContext)) {}
45
46// Returns total buffer size to allocate, and required offset alignment of that allocation.
47// Updates 'levelOffsetsAndRowBytes' with offsets relative to start of the allocation, as well as
48// the aligned destination rowBytes for each level.
49std::pair<size_t, size_t> compute_combined_buffer_size(
50 const Caps* caps,
51 int mipLevelCount,
52 size_t bytesPerBlock,
53 const SkISize& baseDimensions,
54 SkTextureCompressionType compressionType,
55 TArray<std::pair<size_t, size_t>>* levelOffsetsAndRowBytes) {
56 SkASSERT(levelOffsetsAndRowBytes && !levelOffsetsAndRowBytes->size());
57 SkASSERT(mipLevelCount >= 1);
58
59 SkISize compressedBlockDimensions = CompressedDimensionsInBlocks(compressionType,
60 baseDimensions);
61
62 size_t minTransferBufferAlignment =
63 std::max(bytesPerBlock, caps->requiredTransferBufferAlignment());
64 size_t alignedBytesPerRow =
65 caps->getAlignedTextureDataRowBytes(compressedBlockDimensions.width() * bytesPerBlock);
66
67 levelOffsetsAndRowBytes->push_back({0, alignedBytesPerRow});
68 size_t combinedBufferSize = SkAlignTo(alignedBytesPerRow * baseDimensions.height(),
69 minTransferBufferAlignment);
70 SkISize levelDimensions = baseDimensions;
71
72 for (int currentMipLevel = 1; currentMipLevel < mipLevelCount; ++currentMipLevel) {
73 levelDimensions = {std::max(1, levelDimensions.width() / 2),
74 std::max(1, levelDimensions.height() / 2)};
75 compressedBlockDimensions = CompressedDimensionsInBlocks(compressionType, levelDimensions);
76 alignedBytesPerRow = caps->getAlignedTextureDataRowBytes(
77 compressedBlockDimensions.width() * bytesPerBlock);
78 size_t alignedSize = SkAlignTo(alignedBytesPerRow * compressedBlockDimensions.height(),
79 minTransferBufferAlignment);
80 SkASSERT(combinedBufferSize % minTransferBufferAlignment == 0);
81
82 levelOffsetsAndRowBytes->push_back({combinedBufferSize, alignedBytesPerRow});
83 combinedBufferSize += alignedSize;
84 }
85
86 SkASSERT(levelOffsetsAndRowBytes->size() == mipLevelCount);
87 SkASSERT(combinedBufferSize % minTransferBufferAlignment == 0);
88 return {combinedBufferSize, minTransferBufferAlignment};
89}
90
92 sk_sp<TextureProxy> textureProxy,
93 const SkColorInfo& srcColorInfo,
94 const SkColorInfo& dstColorInfo,
96 const SkIRect& dstRect,
97 std::unique_ptr<ConditionalUploadContext> condContext) {
98 const Caps* caps = recorder->priv().caps();
99 SkASSERT(caps->isTexturable(textureProxy->textureInfo()));
101 textureProxy->textureInfo()));
102
103 unsigned int mipLevelCount = levels.size();
104 // The assumption is either that we have no mipmaps, or that our rect is the entire texture
105 SkASSERT(mipLevelCount == 1 || dstRect == SkIRect::MakeSize(textureProxy->dimensions()));
106
107 // We assume that if the texture has mip levels, we either upload to all the levels or just the
108 // first.
109#ifdef SK_DEBUG
110 unsigned int numExpectedLevels = 1;
111 if (textureProxy->textureInfo().mipmapped() == Mipmapped::kYes) {
112 numExpectedLevels = SkMipmap::ComputeLevelCount(textureProxy->dimensions().width(),
113 textureProxy->dimensions().height()) + 1;
114 }
115 SkASSERT(mipLevelCount == 1 || mipLevelCount == numExpectedLevels);
116#endif
117
118 if (dstRect.isEmpty()) {
119 return Invalid();
120 }
121
122 if (mipLevelCount == 1 && !levels[0].fPixels) {
123 return Invalid(); // no data to upload
124 }
125
126 for (unsigned int i = 0; i < mipLevelCount; ++i) {
127 // We do not allow any gaps in the mip data
128 if (!levels[i].fPixels) {
129 return Invalid();
130 }
131 }
132
133 SkColorType supportedColorType;
134 bool isRGB888Format;
135 std::tie(supportedColorType, isRGB888Format) =
136 caps->supportedWritePixelsColorType(dstColorInfo.colorType(),
137 textureProxy->textureInfo(),
138 srcColorInfo.colorType());
139 if (supportedColorType == kUnknown_SkColorType) {
140 return Invalid();
141 }
142
143 const size_t bpp = isRGB888Format ? 3 : SkColorTypeBytesPerPixel(supportedColorType);
144 TArray<std::pair<size_t, size_t>> levelOffsetsAndRowBytes(mipLevelCount);
145
146 auto [combinedBufferSize, minAlignment] = compute_combined_buffer_size(
147 caps,
148 mipLevelCount,
149 bpp,
150 dstRect.size(),
152 &levelOffsetsAndRowBytes);
153 SkASSERT(combinedBufferSize);
154
155 UploadBufferManager* bufferMgr = recorder->priv().uploadBufferManager();
156 auto [writer, bufferInfo] = bufferMgr->getTextureUploadWriter(combinedBufferSize, minAlignment);
157 if (!writer) {
158 SKGPU_LOG_W("Failed to get write-mapped buffer for texture upload of size %zu",
159 combinedBufferSize);
160 return Invalid();
161 }
162
163 UploadInstance upload{bufferInfo.fBuffer, bpp, std::move(textureProxy), std::move(condContext)};
164
165 // Fill in copy data
166 int32_t currentWidth = dstRect.width();
167 int32_t currentHeight = dstRect.height();
168 bool needsConversion = (srcColorInfo != dstColorInfo);
169 for (unsigned int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
170 const size_t trimRowBytes = currentWidth * bpp;
171 const size_t srcRowBytes = levels[currentMipLevel].fRowBytes;
172 const auto [mipOffset, dstRowBytes] = levelOffsetsAndRowBytes[currentMipLevel];
173
174 // copy data into the buffer, skipping any trailing bytes
175 const char* src = (const char*)levels[currentMipLevel].fPixels;
176
177 if (isRGB888Format) {
178 SkASSERT(supportedColorType == kRGB_888x_SkColorType &&
179 dstColorInfo.colorType() == kRGB_888x_SkColorType);
180 SkISize dims = {currentWidth, currentHeight};
181 SkImageInfo srcImageInfo = SkImageInfo::Make(dims, srcColorInfo);
182 SkImageInfo dstImageInfo = SkImageInfo::Make(dims, dstColorInfo);
183
184 const void* rgbConvertSrc = src;
185 size_t rgbSrcRowBytes = srcRowBytes;
187 if (needsConversion) {
188 temp.alloc(dstImageInfo);
189 SkAssertResult(SkConvertPixels(dstImageInfo,
190 temp.writable_addr(),
191 temp.rowBytes(),
192 srcImageInfo,
193 src,
194 srcRowBytes));
195 rgbConvertSrc = temp.addr();
196 rgbSrcRowBytes = temp.rowBytes();
197 }
198 writer.writeRGBFromRGBx(mipOffset,
199 rgbConvertSrc,
200 rgbSrcRowBytes,
201 dstRowBytes,
202 currentWidth,
203 currentHeight);
204 } else if (needsConversion) {
205 SkISize dims = {currentWidth, currentHeight};
206 SkImageInfo srcImageInfo = SkImageInfo::Make(dims, srcColorInfo);
207 SkImageInfo dstImageInfo = SkImageInfo::Make(dims, dstColorInfo);
208
209 writer.convertAndWrite(
210 mipOffset, srcImageInfo, src, srcRowBytes, dstImageInfo, dstRowBytes);
211 } else {
212 writer.write(mipOffset, src, srcRowBytes, dstRowBytes, trimRowBytes, currentHeight);
213 }
214
215 // For mipped data, the dstRect is always the full texture so we don't need to worry about
216 // modifying the TL coord as it will always be 0,0,for all levels.
217 upload.fCopyData.push_back({
218 /*fBufferOffset=*/bufferInfo.fOffset + mipOffset,
219 /*fBufferRowBytes=*/dstRowBytes,
220 /*fRect=*/SkIRect::MakeXYWH(dstRect.left(), dstRect.top(), currentWidth, currentHeight),
221 /*fMipmapLevel=*/currentMipLevel
222 });
223
224 currentWidth = std::max(1, currentWidth / 2);
225 currentHeight = std::max(1, currentHeight / 2);
226 }
227
228 ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%dx%d]",
229 mipLevelCount > 1 ? "MipMap " : "",
230 dstRect.width(), dstRect.height());
231
232 return upload;
233}
234
235UploadInstance UploadInstance::MakeCompressed(Recorder* recorder,
236 sk_sp<TextureProxy> textureProxy,
237 const void* data,
238 size_t dataSize) {
239 if (!data) {
240 return Invalid(); // no data to upload
241 }
242
243 const TextureInfo& texInfo = textureProxy->textureInfo();
244
245 const Caps* caps = recorder->priv().caps();
246 SkASSERT(caps->isTexturable(texInfo));
247
248 SkTextureCompressionType compression = texInfo.compressionType();
249 if (compression == SkTextureCompressionType::kNone) {
250 return Invalid();
251 }
252
253 // Create a transfer buffer and fill with data.
254 const SkISize dimensions = textureProxy->dimensions();
256 SkDEBUGCODE(size_t computedSize =) SkCompressedDataSize(compression,
257 dimensions,
258 &srcMipOffsets,
259 texInfo.mipmapped() == Mipmapped::kYes);
260 SkASSERT(computedSize == dataSize);
261
262 unsigned int mipLevelCount = srcMipOffsets.size();
263 size_t bytesPerBlock = SkCompressedBlockSize(compression);
264 TArray<std::pair<size_t, size_t>> levelOffsetsAndRowBytes(mipLevelCount);
265 auto [combinedBufferSize, minAlignment] = compute_combined_buffer_size(
266 caps,
267 mipLevelCount,
268 bytesPerBlock,
269 dimensions,
270 compression,
271 &levelOffsetsAndRowBytes);
272 SkASSERT(combinedBufferSize);
273
274 UploadBufferManager* bufferMgr = recorder->priv().uploadBufferManager();
275 auto [writer, bufferInfo] = bufferMgr->getTextureUploadWriter(combinedBufferSize, minAlignment);
276
277 std::vector<BufferTextureCopyData> copyData(mipLevelCount);
278
279 if (!bufferInfo.fBuffer) {
280 SKGPU_LOG_W("Failed to get write-mapped buffer for texture upload of size %zu",
281 combinedBufferSize);
282 return Invalid();
283 }
284
285 UploadInstance upload{bufferInfo.fBuffer, bytesPerBlock, std::move(textureProxy)};
286
287 // Fill in copy data
288 int32_t currentWidth = dimensions.width();
289 int32_t currentHeight = dimensions.height();
290 for (unsigned int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
291 SkISize blockDimensions = CompressedDimensionsInBlocks(compression,
292 {currentWidth, currentHeight});
293 int32_t blockHeight = blockDimensions.height();
294
295 const size_t trimRowBytes = CompressedRowBytes(compression, currentWidth);
296 const size_t srcRowBytes = trimRowBytes;
297 const auto [dstMipOffset, dstRowBytes] = levelOffsetsAndRowBytes[currentMipLevel];
298
299 // copy data into the buffer, skipping any trailing bytes
300 const void* src = SkTAddOffset<const void>(data, srcMipOffsets[currentMipLevel]);
301
302 writer.write(dstMipOffset, src, srcRowBytes, dstRowBytes, trimRowBytes, blockHeight);
303
304 int32_t copyWidth = currentWidth;
305 int32_t copyHeight = currentHeight;
307 SkISize oneBlockDims = CompressedDimensions(compression, {1, 1});
308 copyWidth = SkAlignTo(copyWidth, oneBlockDims.fWidth);
309 copyHeight = SkAlignTo(copyHeight, oneBlockDims.fHeight);
310 }
311
312 upload.fCopyData.push_back({
313 /*fBufferOffset=*/bufferInfo.fOffset + dstMipOffset,
314 /*fBufferRowBytes=*/dstRowBytes,
315 /*fRect=*/SkIRect::MakeXYWH(0, 0, copyWidth, copyHeight),
316 /*fMipLevel=*/currentMipLevel
317 });
318
319 currentWidth = std::max(1, currentWidth / 2);
320 currentHeight = std::max(1, currentHeight / 2);
321 }
322
323 ATRACE_ANDROID_FRAMEWORK("Upload Compressed %sTexture [%dx%d]",
324 mipLevelCount > 1 ? "MipMap " : "",
325 dimensions.width(),
326 dimensions.height());
327
328 return upload;
329}
330
331bool UploadInstance::prepareResources(ResourceProvider* resourceProvider) {
332 // While most uploads are to already instantiated proxies (e.g. for client-created texture
333 // images) it is possible that writePixels() was issued as the first operation on a scratch
334 // Device, or that this is the first upload to the raster or text atlas proxies.
335 // TODO: Determine how to instantatiate textues in this case; atlas proxies shouldn't really be
336 // "scratch" because they aren't going to be reused for anything else in a Recording. At the
337 // same time, it could still go through the ScratchResourceManager and just never return them,
338 // which is no different from instantiating them directly with the ResourceProvider.
339 if (!TextureProxy::InstantiateIfNotLazy(resourceProvider, fTextureProxy.get())) {
340 SKGPU_LOG_E("Could not instantiate texture proxy for UploadTask!");
341 return false;
342 }
343 return true;
344}
345
346Task::Status UploadInstance::addCommand(Context* context,
347 CommandBuffer* commandBuffer,
348 Task::ReplayTargetData replayData) const {
349 using Status = Task::Status;
350 SkASSERT(fTextureProxy && fTextureProxy->isInstantiated());
351
352 if (fConditionalContext && !fConditionalContext->needsUpload(context)) {
353 // Assume that if a conditional context says to dynamically not upload that another
354 // time through the tasks should try to upload again.
355 return Status::kSuccess;
356 }
357
358 if (fTextureProxy->texture() != replayData.fTarget) {
359 // The CommandBuffer doesn't take ownership of the upload buffer here; it's owned by
360 // UploadBufferManager, which will transfer ownership in transferToCommandBuffer.
361 if (!commandBuffer->copyBufferToTexture(fBuffer,
362 fTextureProxy->refTexture(),
363 fCopyData.data(),
364 fCopyData.size())) {
365 return Status::kFail;
366 }
367 } else {
368 // Here we assume that multiple copies in a single UploadInstance are always used for
369 // mipmaps of a single image, and that we won't ever copy to a replay target with mipmaps.
370 SkASSERT(fCopyData.size() == 1);
371 const BufferTextureCopyData& copyData = fCopyData[0];
372 SkIRect dstRect = copyData.fRect;
373 dstRect.offset(replayData.fTranslation);
374 SkIRect croppedDstRect = dstRect;
375 if (!croppedDstRect.intersect(SkIRect::MakeSize(fTextureProxy->dimensions()))) {
376 // The replay translation can change on each insert, so subsequent replays may
377 // actually intersect the copy rect.
378 return Status::kSuccess;
379 }
380
381 BufferTextureCopyData transformedCopyData = copyData;
382 transformedCopyData.fBufferOffset +=
383 (croppedDstRect.y() - dstRect.y()) * copyData.fBufferRowBytes +
384 (croppedDstRect.x() - dstRect.x()) * fBytesPerPixel;
385 transformedCopyData.fRect = croppedDstRect;
386
387 if (!commandBuffer->copyBufferToTexture(fBuffer,
388 fTextureProxy->refTexture(),
389 &transformedCopyData, 1)) {
390 return Status::kFail;
391 }
392 }
393
394 // The conditional context will return false if the upload should not happen anymore. If there's
395 // no context assume that the upload should always be executed on replay.
396 if (!fConditionalContext || fConditionalContext->uploadSubmitted()) {
397 return Status::kSuccess;
398 } else {
399 return Status::kDiscard;
400 }
401}
402
403//---------------------------------------------------------------------------
404
405bool UploadList::recordUpload(Recorder* recorder,
406 sk_sp<TextureProxy> textureProxy,
407 const SkColorInfo& srcColorInfo,
408 const SkColorInfo& dstColorInfo,
410 const SkIRect& dstRect,
411 std::unique_ptr<ConditionalUploadContext> condContext) {
412 UploadInstance instance = UploadInstance::Make(recorder, std::move(textureProxy),
413 srcColorInfo, dstColorInfo,
414 levels, dstRect, std::move(condContext));
415 if (!instance.isValid()) {
416 return false;
417 }
418
419 fInstances.emplace_back(std::move(instance));
420 return true;
421}
422
423//---------------------------------------------------------------------------
424
426 SkASSERT(uploadList);
427 if (!uploadList->size()) {
428 return nullptr;
429 }
430 return sk_sp<UploadTask>(new UploadTask(std::move(uploadList->fInstances)));
431}
432
434 if (!instance.isValid()) {
435 return nullptr;
436 }
437 return sk_sp<UploadTask>(new UploadTask(std::move(instance)));
438}
439
440UploadTask::UploadTask(skia_private::TArray<UploadInstance>&& instances)
441 : fInstances(std::move(instances)) {}
442
443UploadTask::UploadTask(UploadInstance instance) {
444 fInstances.emplace_back(std::move(instance));
445}
446
448
452 for (int i = 0; i < fInstances.size(); ++i) {
453 // No upload should be invalidated before prepareResources() is called.
454 SkASSERT(fInstances[i].isValid());
455 if (!fInstances[i].prepareResources(resourceProvider)) {
456 return Status::kFail;
457 }
458 }
459
460 return Status::kSuccess;
461}
462
464 CommandBuffer* commandBuffer,
465 ReplayTargetData replayData) {
466 int discardCount = 0;
467 for (int i = 0; i < fInstances.size(); ++i) {
468 if (!fInstances[i].isValid()) {
469 discardCount++;
470 continue;
471 }
472 Status status = fInstances[i].addCommand(context, commandBuffer, replayData);
473 if (status == Status::kFail) {
474 return Status::kFail;
475 } else if (status == Status::kDiscard) {
476 fInstances[i] = UploadInstance::Invalid();
477 discardCount++;
478 }
479 }
480
481 if (discardCount == fInstances.size()) {
482 return Status::kDiscard;
483 } else {
484 return Status::kSuccess;
485 }
486}
487
488} // namespace skgpu::graphite
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
#define SKGPU_LOG_W(fmt,...)
Definition: Log.h:40
static constexpr size_t SkAlignTo(size_t x, size_t alignment)
Definition: SkAlign.h:33
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkColorType
Definition: SkColorType.h:19
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:25
@ kUnknown_SkColorType
uninitialized
Definition: SkColorType.h:20
size_t SkCompressedDataSize(SkTextureCompressionType type, SkISize dimensions, TArray< size_t > *individualMipOffsets, bool mipmapped)
size_t SkCompressedBlockSize(SkTextureCompressionType type)
bool SkConvertPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB)
SK_API int SkColorTypeBytesPerPixel(SkColorType ct)
Definition: SkImageInfo.cpp:16
SkTextureCompressionType
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
#define ATRACE_ANDROID_FRAMEWORK(fmt,...)
static sk_sp< SkImage > upload(const sk_sp< SkSurface > &surf, SkColor color)
void alloc(const SkImageInfo &)
SkColorType colorType() const
Definition: SkImageInfo.h:140
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition: SkMipmap.cpp:134
size_t rowBytes() const
Definition: SkPixmap.h:145
void * writable_addr() const
Definition: SkPixmap.h:483
const void * addr() const
Definition: SkPixmap.h:153
constexpr size_t size() const
Definition: SkSpan_impl.h:95
bool isTexturable(const TextureInfo &) const
Definition: Caps.cpp:66
virtual std::pair< SkColorType, bool > supportedWritePixelsColorType(SkColorType dstColorType, const TextureInfo &dstTextureInfo, SkColorType srcColorType) const =0
bool fullCompressedUploadSizeMustAlignToBlockDims() const
Definition: Caps.h:291
size_t getAlignedTextureDataRowBytes(size_t rowBytes) const
Definition: Caps.h:166
bool areColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo &) const
Definition: Caps.cpp:85
size_t requiredTransferBufferAlignment() const
Definition: Caps.h:163
bool copyBufferToTexture(const Buffer *, sk_sp< Texture >, const BufferTextureCopyData *, int count)
const Caps * caps() const
Definition: RecorderPriv.h:31
UploadBufferManager * uploadBufferManager()
Definition: RecorderPriv.h:59
Mipmapped mipmapped() const
Definition: TextureInfo.h:79
SkTextureCompressionType compressionType() const
std::tuple< TextureUploadWriter, BindBufferInfo > getTextureUploadWriter(size_t requiredBytes, size_t requiredAlignment)
static UploadInstance Invalid()
Definition: UploadTask.h:84
UploadInstance & operator=(UploadInstance &&)
Status prepareResources(ResourceProvider *, ScratchResourceManager *, const RuntimeEffectDictionary *) override
Definition: UploadTask.cpp:449
Status addCommands(Context *, CommandBuffer *, ReplayTargetData) override
Definition: UploadTask.cpp:463
int size() const
Definition: SkTArray.h:421
@ kSuccess
Definition: embedder.h:73
VkInstance instance
Definition: main.cc:48
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
std::pair< size_t, size_t > compute_combined_buffer_size(const Caps *caps, int mipLevelCount, size_t bytesPerBlock, const SkISize &baseDimensions, SkTextureCompressionType compressionType, TArray< std::pair< size_t, size_t > > *levelOffsetsAndRowBytes)
Definition: UploadTask.cpp:49
Task::Status Status
Definition: TaskList.cpp:15
SkISize CompressedDimensionsInBlocks(SkTextureCompressionType type, SkISize baseDimensions)
Definition: DataUtils.cpp:210
size_t CompressedRowBytes(SkTextureCompressionType type, int width)
Definition: DataUtils.cpp:179
SkISize CompressedDimensions(SkTextureCompressionType type, SkISize baseDimensions)
Definition: DataUtils.cpp:195
Definition: ref_ptr.h:256
Definition: upload.py:1
Definition: SkRect.h:32
constexpr int32_t x() const
Definition: SkRect.h:141
constexpr int32_t y() const
Definition: SkRect.h:148
bool intersect(const SkIRect &r)
Definition: SkRect.h:513
constexpr int32_t top() const
Definition: SkRect.h:120
constexpr SkISize size() const
Definition: SkRect.h:172
constexpr int32_t height() const
Definition: SkRect.h:165
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66
constexpr int32_t width() const
Definition: SkRect.h:158
void offset(int32_t dx, int32_t dy)
Definition: SkRect.h:367
bool isEmpty() const
Definition: SkRect.h:202
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
constexpr int32_t left() const
Definition: SkRect.h:113
Definition: SkSize.h:16
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63