58#if defined(GRAPHITE_TEST_UTILS)
62#include "webgpu/webgpu_cpp.h"
68#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(this->singleOwner())
71 static std::atomic<uint32_t> nextID{1};
74 id = nextID.fetch_add(1, std::memory_order_relaxed);
81 std::unique_ptr<QueueManager> queueManager,
83 : fSharedContext(
std::move(sharedContext))
84 , fQueueManager(
std::move(queueManager))
88 fResourceProvider = fSharedContext->makeResourceProvider(&fSingleOwner,
91 fMappedBufferManager = std::make_unique<ClientMappedBufferManager>(this->
contextID());
92#if defined(GRAPHITE_TEST_UTILS)
94 fStoreContextRefInRecorder =
options.fOptionsPriv->fStoreContextRefInRecorder;
100#if defined(GRAPHITE_TEST_UTILS)
102 for (
auto& recorder : fTrackedRecorders) {
103 recorder->priv().setContext(
nullptr);
108bool Context::finishInitialization() {
109 SkASSERT(!fSharedContext->rendererProvider());
112 std::unique_ptr<RendererProvider> renderers{
113 new RendererProvider(fSharedContext->caps(), &bufferManager)};
115 auto result = bufferManager.finalize(
this, fQueueManager.get(), fSharedContext->globalCache());
122 !fQueueManager->submitToGpu()) {
123 SKGPU_LOG_W(
"Failed to submit initial command buffer for Context creation.\n");
126 fSharedContext->setRendererProvider(std::move(renderers));
136 auto recorder = std::unique_ptr<Recorder>(
new Recorder(fSharedContext,
options,
nullptr));
137#if defined(GRAPHITE_TEST_UTILS)
138 if (fStoreContextRefInRecorder) {
139 recorder->priv().setContext(
this);
145std::unique_ptr<Recorder> Context::makeInternalRecorder()
const {
153 return std::unique_ptr<Recorder>(
new Recorder(fSharedContext, {},
this));
159 return fQueueManager->addRecording(
info,
this);
165 if (syncToCpu ==
SyncToCpu::kYes && !fSharedContext->caps()->allowCpuSync()) {
166 SKGPU_LOG_E(
"SyncToCpu::kYes not supported with ContextOptions::fNeverYieldToWebGPU. "
167 "The parameter is ignored and no synchronization will occur.");
170 bool success = fQueueManager->submitToGpu();
171 this->checkForFinishedWork(syncToCpu);
177template <
typename SrcPixels>
178struct Context::AsyncParams {
179 const SrcPixels* fSrcImage;
186 template <
typename S>
187 AsyncParams<S> withNewSource(
const S* newPixels,
const SkIRect& newSrcRect)
const {
188 return AsyncParams<S>{newPixels, newSrcRect,
189 fDstImageInfo, fCallback, fCallbackContext};
193 (*fCallback)(fCallbackContext,
nullptr);
196 bool validate()
const {
200 if (fSrcImage->isProtected()) {
213template <
typename ReadFn,
typename... ExtraArgs>
214void Context::asyncRescaleAndReadImpl(ReadFn
Context::* asyncRead,
217 const AsyncParams<SkImage>&
params,
218 ExtraArgs... extraParams) {
223 if (
params.fSrcRect.size() ==
params.fDstImageInfo.dimensions()) {
225 return (this->*asyncRead)(
nullptr,
params, extraParams...);
229 std::unique_ptr<Recorder> recorder = this->makeInternalRecorder();
237 SKGPU_LOG_W(
"AsyncRead failed because rescaling failed");
240 (this->*asyncRead)(std::move(recorder),
241 params.withNewSource(scaledImage.
get(),
params.fDstImageInfo.bounds()),
252 this->asyncRescaleAndReadImpl(&Context::asyncReadPixels,
253 rescaleGamma, rescaleMode,
270 return this->asyncReadTexture(
nullptr,
271 {proxy, srcRect, dstImageInfo,
callback, callbackContext},
272 surface->imageInfo().colorInfo());
286void Context::asyncReadPixels(std::unique_ptr<Recorder> recorder,
287 const AsyncParams<SkImage>&
params) {
289 "width",
params.fSrcRect.width(),
290 "height",
params.fSrcRect.height());
294 const Caps* caps = fSharedContext->caps();
300 recorder = this->makeInternalRecorder();
305 params.fDstImageInfo.colorInfo(),
309 "AsyncReadPixelsFallbackTexture");
311 SKGPU_LOG_W(
"AsyncRead failed because copy-as-drawing into a readable format failed");
315 return this->asyncReadPixels(std::move(recorder),
321 this->asyncReadTexture(std::move(recorder),
params.withNewSource(view.
proxy(),
params.fSrcRect),
322 params.fSrcImage->imageInfo().colorInfo());
325void Context::asyncReadTexture(std::unique_ptr<Recorder> recorder,
326 const AsyncParams<TextureProxy>&
params,
334 PixelTransferResult transferResult = this->transferPixels(recorder.get(),
337 params.fDstImageInfo.colorInfo(),
340 if (!transferResult.fTransferBuffer) {
345 this->finalizeAsyncReadPixels(std::move(recorder),
346 {&transferResult, 1},
364 std::move(dstColorSpace));
365 this->asyncRescaleAndReadImpl(&Context::asyncReadPixelsYUV420,
366 rescaleGamma, rescaleMode,
408 std::move(dstColorSpace));
409 this->asyncRescaleAndReadImpl(&Context::asyncReadPixelsYUV420,
410 rescaleGamma, rescaleMode,
436void Context::asyncReadPixelsYUV420(std::unique_ptr<Recorder> recorder,
437 const AsyncParams<SkImage>&
params,
440 "width",
params.fSrcRect.width(),
441 "height",
params.fSrcRect.height());
446 recorder = this->makeInternalRecorder();
451 std::string_view label,
454 PixelTransferResult*
result) {
470 paint.setShader(std::move(imgShader));
480 SkCanvas* canvas = dstSurface->getCanvas();
487 *
result = this->transferPixels(recorder.get(),
488 dstSurface->backingTextureProxy(),
489 dstSurface->imageInfo().colorInfo(),
502 PixelTransferResult transfers[4];
510 std::fill_n(yM, 15, 0.f);
511 std::copy_n(baseM + 0, 5, yM + 15);
512 if (!copyPlane(yaInfo,
"AsyncReadPixelsYPlane", yM, texMatrix, &transfers[0])) {
523 !copyPlane(yaInfo,
"AsyncReadPixelsAPlane",
nullptr, texMatrix, &transfers[3])) {
532 std::fill_n(uM, 15, 0.f);
533 std::copy_n(baseM + 5, 5, uM + 15);
534 if (!copyPlane(uvInfo,
"AsyncReadPixelsUPlane", uM, texMatrix, &transfers[1])) {
540 std::fill_n(vM, 15, 0.f);
541 std::copy_n(baseM + 10, 5, vM + 15);
542 if (!copyPlane(uvInfo,
"AsyncReadPixelsVPlane", vM, texMatrix, &transfers[2])) {
546 this->finalizeAsyncReadPixels(std::move(recorder),
547 {transfers, readAlpha ? 4 : 3},
552void Context::finalizeAsyncReadPixels(std::unique_ptr<Recorder> recorder,
560 std::unique_ptr<Recording> recording = recorder->snap();
565 InsertRecordingInfo recordingInfo;
566 recordingInfo.fRecording = recording.get();
574 struct AsyncReadFinishContext {
577 ClientMappedBufferManager* fMappedBufferManager;
578 std::array<PixelTransferResult, 4> fTransferResults;
581 auto finishContext = std::make_unique<AsyncReadFinishContext>();
582 finishContext->fClientCallback =
callback;
583 finishContext->fClientContext = callbackContext;
584 finishContext->fMappedBufferManager = fMappedBufferManager.get();
588 for (
size_t i = 0;
i < transferResults.
size(); ++
i) {
589 finishContext->fTransferResults[
i] = std::move(transferResults[
i]);
590 if (fSharedContext->caps()->bufferMapsAreAsync()) {
591 buffersToAsyncMap.
push_back(finishContext->fTransferResults[
i].fTransferBuffer);
595 InsertFinishInfo
info;
596 info.fFinishedContext = finishContext.release();
598 std::unique_ptr<const AsyncReadFinishContext> context(
599 reinterpret_cast<const AsyncReadFinishContext*
>(c));
602 ClientMappedBufferManager*
manager = context->fMappedBufferManager;
603 std::unique_ptr<AsyncReadResult>
result;
605 result = std::make_unique<AsyncReadResult>(
manager->ownerID());
607 for (
const auto& r : context->fTransferResults) {
608 if (!r.fTransferBuffer) {
616 if (!
result && r.fTransferBuffer->isUnmappable()) {
617 r.fTransferBuffer->unmap();
620 (*context->fClientCallback)(context->fClientContext, std::move(
result));
626 if (!fQueueManager->addFinishInfo(
info, fResourceProvider.get(), buffersToAsyncMap)) {
627 SKGPU_LOG_E(
"Failed to register finish callbacks for asyncReadPixels.");
632Context::PixelTransferResult Context::transferPixels(
Recorder* recorder,
633 const TextureProxy* srcProxy,
640 const Caps* caps = fSharedContext->caps();
641 if (!srcProxy || !caps->supportsReadPixels(srcProxy->textureInfo())) {
648 std::tie(supportedColorType, isRGB888Format) =
649 caps->supportedReadPixelsColorType(srcColorType,
650 srcProxy->textureInfo(),
661 if ((~legalReadChannels & dstChannels) & srcChannels) {
666 size_t rowBytes = caps->getAlignedTextureDataRowBytes(bpp * srcRect.
width());
667 size_t size =
SkAlignTo(rowBytes * srcRect.
height(), caps->requiredTransferBufferAlignment());
681 const bool addTasksDirectly = !
SkToBool(recorder);
683 if (!copyTask || (addTasksDirectly && !fQueueManager->addTask(copyTask.
get(),
this))) {
685 }
else if (!addTasksDirectly) {
688 recorder->
priv().
add(std::move(copyTask));
691 if (!syncTask || (addTasksDirectly && !fQueueManager->addTask(syncTask.
get(),
this))) {
693 }
else if (!addTasksDirectly) {
694 recorder->
priv().
add(std::move(syncTask));
697 PixelTransferResult
result;
704 if (readColorInfo != dstColorInfo || isRGB888Format) {
709 result.fPixelConverter = [dstInfo, srcInfo, rowBytes, isRGB888Format](
710 void*
dst,
const void*
src) {
712 size_t srcRowBytes = rowBytes;
713 if (isRGB888Format) {
716 auto* sRow =
reinterpret_cast<const char*
>(
src);
718 for (
int y = 0;
y < srcInfo.height(); ++
y, sRow += srcRowBytes, tRow += tRowBytes) {
719 for (
int x = 0;
x < srcInfo.width(); ++
x) {
721 auto t = tRow +
x*
sizeof(uint32_t);
723 t[3] =
static_cast<char>(0xFF);
727 srcRowBytes = tRowBytes;
730 srcInfo,
src, srcRowBytes));
733 result.fRowBytes = rowBytes;
739void Context::checkForFinishedWork(
SyncToCpu syncToCpu) {
742 fQueueManager->checkForFinishedWork(syncToCpu);
743 fMappedBufferManager->process();
756 fResourceProvider->deleteBackendTexture(
texture);
764 fResourceProvider->freeGpuResources();
772 auto purgeTime = skgpu::StdSteadyClock::now() - msNotUsed;
773 fResourceProvider->purgeResourcesNotUsedSince(purgeTime);
778 return fResourceProvider->getResourceCacheCurrentBudgetedBytes();
783 return fResourceProvider->getResourceCacheLimit();
788 fResourceProvider->dumpMemoryStatistics(traceMemoryDump);
794 return fSharedContext->isDeviceLost();
798 return fSharedContext->caps()->maxTextureSize();
807#if defined(GRAPHITE_TEST_UTILS)
808bool ContextPriv::readPixels(
const SkPixmap& pm,
811 int srcX,
int srcY) {
813 struct AsyncContext {
814 bool fCalled =
false;
815 std::unique_ptr<const SkImage::AsyncReadResult>
fResult;
818 auto asyncCallback = [](
void* c, std::unique_ptr<const SkImage::AsyncReadResult>
out) {
819 auto context =
static_cast<AsyncContext*
>(c);
820 context->fResult = std::move(
out);
821 context->fCalled =
true;
829 if (!fContext->fSharedContext->caps()->supportsReadPixels(textureProxy->
textureInfo())) {
834 fContext->asyncReadPixels(
nullptr,
837 fContext->asyncReadTexture(
nullptr,
838 {textureProxy,
rect, pm.
info(), asyncCallback, &asyncContext},
842 if (fContext->fSharedContext->caps()->allowCpuSync()) {
847 while (!asyncContext.fCalled) {
849 auto dawnContext =
static_cast<DawnSharedContext*
>(fContext->fSharedContext.get());
850 dawnContext->device().Tick();
855 SK_ABORT(
"Only Dawn supports non-synching contexts.");
859 if (!asyncContext.fResult) {
868void ContextPriv::deregisterRecorder(
const Recorder* recorder) {
870 for (auto it = fContext->fTrackedRecorders.
begin();
871 it != fContext->fTrackedRecorders.end();
873 if (*it == recorder) {
874 fContext->fTrackedRecorders.erase(it);
905 std::unique_ptr<QueueManager> queueManager,
907 auto context = std::unique_ptr<Context>(
new Context(std::move(sharedContext),
908 std::move(queueManager),
910 if (context && context->finishInitialization()) {
#define ASSERT_SINGLE_OWNER
static void fail(const SkString &err)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
for(const auto glyph :glyphs)
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
#define SKGPU_LOG_E(fmt,...)
#define SKGPU_LOG_W(fmt,...)
#define SKGPU_ASSERT_SINGLE_OWNER(obj)
static constexpr size_t SkAlignTo(size_t x, size_t alignment)
@ kOpaque_SkAlphaType
pixel is opaque
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SK_ABORT(message,...)
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kUnknown_SkColorType
uninitialized
bool SkConvertPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB)
static uint32_t SkColorTypeChannelFlags(SkColorType ct)
static bool SkColorInfoIsValid(const SkColorInfo &info)
static bool SkImageInfoIsValid(const SkImageInfo &info)
SK_API int SkColorTypeBytesPerPixel(SkColorType ct)
static void SkRectMemcpy(void *dst, size_t dstRB, const void *src, size_t srcRB, size_t trimRowBytes, int rowCount)
sk_sp< T > sk_ref_sp(T *obj)
LoopControlFlowInfo fResult
static const SkSurface_Base * asConstSB(const SkSurface *surface)
static constexpr bool SkToBool(const T &x)
static constexpr uint32_t SK_InvalidUniqueID
static constexpr uint32_t SK_InvalidGenID
void SkColorMatrix_RGB2YUV(SkYUVColorSpace cs, float m[20])
void alloc(const SkImageInfo &)
void drawPaint(const SkPaint &paint)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
SkColorInfo makeColorType(SkColorType newColorType) const
SkColorType colorType() const
void(ReadPixelsContext, std::unique_ptr< const AsyncReadResult >) ReadPixelsCallback
static SkMatrix Translate(SkScalar dx, SkScalar dy)
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
const SkImageInfo & info() const
void * writable_addr() const
const void * addr() const
constexpr size_t size() const
static PathAtlasFlagsBitMask QueryPathAtlasSupport(const Caps *)
SkEnumBitMask< PathAtlasFlags > PathAtlasFlagsBitMask
virtual bool supportsReadPixels(const TextureInfo &textureInfo) const =0
static std::unique_ptr< Context > MakeContext(sk_sp< SharedContext >, std::unique_ptr< QueueManager >, const ContextOptions &)
const Caps * caps() const
static Context::ContextID Next()
size_t maxBudgetedBytes() const
ContextID contextID() const
BackendApi backend() const
int maxTextureSize() const
void asyncRescaleAndReadPixelsYUV420(const SkImage *, SkYUVColorSpace yuvColorSpace, sk_sp< SkColorSpace > dstColorSpace, const SkIRect &srcRect, const SkISize &dstSize, SkImage::RescaleGamma rescaleGamma, SkImage::RescaleMode rescaleMode, SkImage::ReadPixelsCallback callback, SkImage::ReadPixelsContext context)
std::unique_ptr< Recorder > makeRecorder(const RecorderOptions &={})
void asyncRescaleAndReadPixelsYUVA420(const SkImage *, SkYUVColorSpace yuvColorSpace, sk_sp< SkColorSpace > dstColorSpace, const SkIRect &srcRect, const SkISize &dstSize, SkImage::RescaleGamma rescaleGamma, SkImage::RescaleMode rescaleMode, SkImage::ReadPixelsCallback callback, SkImage::ReadPixelsContext context)
void performDeferredCleanup(std::chrono::milliseconds msNotUsed)
bool submit(SyncToCpu=SyncToCpu::kNo)
void deleteBackendTexture(const BackendTexture &)
bool insertRecording(const InsertRecordingInfo &)
void checkAsyncWorkCompletion()
bool supportsProtectedContent() const
size_t currentBudgetedBytes() const
Context(const Context &)=delete
void dumpMemoryStatistics(SkTraceMemoryDump *traceMemoryDump) const
void asyncRescaleAndReadPixels(const SkImage *image, const SkImageInfo &dstImageInfo, const SkIRect &srcRect, SkImage::RescaleGamma rescaleGamma, SkImage::RescaleMode rescaleMode, SkImage::ReadPixelsCallback callback, SkImage::ReadPixelsContext context)
bool hasUnfinishedGpuWork() const
bool isDeviceLost() const
static sk_sp< CopyTextureToBufferTask > Make(sk_sp< TextureProxy >, SkIRect srcRect, sk_sp< Buffer >, size_t bufferOffset, size_t bufferRowBytes)
static sk_sp< Surface > MakeScratch(Recorder *recorder, const SkImageInfo &info, std::string_view label, Budgeted budgeted=Budgeted::kYes, Mipmapped mipmapped=Mipmapped::kNo, SkBackingFit backingFit=SkBackingFit::kApprox)
static sk_sp< SynchronizeToCpuTask > Make(sk_sp< Buffer >)
TextureProxy * proxy() const
const TextureInfo & textureInfo() const
static const char * begin(const StringSlice &s)
const EmbeddedViewParams * params
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
sk_sp< const SkImage > image
sk_sp< SkBlender > blender SkRect rect
SkSamplingOptions sampling
SK_API sk_sp< SkImage > AsImage(sk_sp< const SkSurface >)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font manager
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
sk_sp< SkImage > RescaleImage(Recorder *recorder, const SkImage *srcImage, SkIRect srcIRect, const SkImageInfo &dstInfo, SkImage::RescaleGamma rescaleGamma, SkImage::RescaleMode rescaleMode)
void Flush(sk_sp< SkSurface > surface)
void * GpuFinishedContext
TextureProxyView AsView(const SkImage *image)
sk_sp< Image > CopyAsDraw(Recorder *recorder, const SkImage *image, const SkIRect &subset, const SkColorInfo &dstColorInfo, Budgeted budgeted, Mipmapped mipmapped, SkBackingFit backingFit, std::string_view label)
constexpr SkISize size() const
constexpr int32_t height() const
static constexpr SkIRect MakeSize(const SkISize &size)
constexpr int32_t width() const
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
bool contains(int32_t x, int32_t y) const
SkImageInfo makeWH(int newWidth, int newHeight) const
const SkColorInfo & colorInfo() const
size_t minRowBytes() const
SkISize dimensions() const
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
ContextOptionsPriv * fOptionsPriv
#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)