56#if defined(GRAPHITE_TEST_UTILS)
60#include "webgpu/webgpu_cpp.h"
66#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(this->singleOwner())
69 static std::atomic<uint32_t> nextID{1};
72 id = nextID.fetch_add(1, std::memory_order_relaxed);
79 std::unique_ptr<QueueManager> queueManager,
81 : fSharedContext(
std::move(sharedContext))
82 , fQueueManager(
std::move(queueManager))
86 fResourceProvider = fSharedContext->makeResourceProvider(&fSingleOwner,
89 fMappedBufferManager = std::make_unique<ClientMappedBufferManager>(this->
contextID());
90#if defined(GRAPHITE_TEST_UTILS)
92 fStoreContextRefInRecorder =
options.fOptionsPriv->fStoreContextRefInRecorder;
98#if defined(GRAPHITE_TEST_UTILS)
100 for (
auto& recorder : fTrackedRecorders) {
101 recorder->priv().setContext(
nullptr);
106bool Context::finishInitialization() {
107 SkASSERT(!fSharedContext->rendererProvider());
110 std::unique_ptr<RendererProvider> renderers{
111 new RendererProvider(fSharedContext->caps(), &bufferManager)};
113 auto result = bufferManager.finalize(
this, fQueueManager.get(), fSharedContext->globalCache());
120 !fQueueManager->submitToGpu()) {
121 SKGPU_LOG_W(
"Failed to submit initial command buffer for Context creation.\n");
124 fSharedContext->setRendererProvider(std::move(renderers));
133 auto recorder = std::unique_ptr<Recorder>(
new Recorder(fSharedContext,
options));
134#if defined(GRAPHITE_TEST_UTILS)
135 if (fStoreContextRefInRecorder) {
136 recorder->priv().setContext(
this);
145 return fQueueManager->addRecording(
info,
this);
151 if (syncToCpu ==
SyncToCpu::kYes && !fSharedContext->caps()->allowCpuSync()) {
152 SKGPU_LOG_E(
"SyncToCpu::kYes not supported with ContextOptions::fNeverYieldToWebGPU. "
153 "The parameter is ignored and no synchronization will occur.");
156 bool success = fQueueManager->submitToGpu();
157 this->checkForFinishedWork(syncToCpu);
189 return this->asyncReadPixels(proxyView.
proxy(),
198 std::unique_ptr<Recorder> recorder = this->
makeRecorder();
212 std::unique_ptr<Recording> recording = recorder->snap();
224 SkASSERT(scaledImage->imageInfo() == dstImageInfo);
227 const TextureProxyView& scaledProxyView = scaledGraphiteImage->textureProxyView();
229 this->asyncReadPixels(scaledProxyView.
proxy(),
282 const Caps* caps = fSharedContext->caps();
283 if (!caps->supportsReadPixels(proxy->
textureInfo())) {
303 TextureProxyView view(
sk_ref_sp(proxy), swizzle);
304 auto srcImage = sk_make_sp<Image>(view, srcImageInfo.
colorInfo());
308 surface->getCanvas()->drawImage(srcImage,
309 -srcRect.
x(), -srcRect.
y(),
313 auto recording = recorder->snap();
314 InsertRecordingInfo recordingInfo;
315 recordingInfo.fRecording = recording.
get();
318 this->asyncReadPixels(
static_cast<Surface*
>(
surface.get())->readSurfaceView().proxy(),
328 PixelTransferResult transferResult = this->transferPixels(proxy, srcImageInfo,
329 dstColorInfo, srcRect);
331 if (!transferResult.fTransferBuffer) {
337 this->finalizeAsyncReadPixels({&transferResult, 1},
callback, callbackContext);
349 this->asyncRescaleAndReadPixelsYUV420Impl(
image,
396 this->asyncRescaleAndReadPixelsYUV420Impl(
image,
434void Context::asyncRescaleAndReadPixelsYUV420Impl(
const SkImage*
image,
456 std::unique_ptr<Recorder> recorder = this->
makeRecorder();
458 if (srcRect.
size() == dstSize &&
460 dstColorSpace.
get())) {
462 return this->asyncReadPixelsYUV420(recorder.get(),
486 this->asyncReadPixelsYUV420(recorder.get(),
495void Context::asyncReadPixelsYUV420(
Recorder* recorder,
516 if (!ySurface || !uSurface || !vSurface || (readAlpha && !aSurface)) {
523 auto drawPlane = [](
SkSurface* dstSurface,
531 sampling, texMatrix);
532 paint.setShader(std::move(imgShader));
536 paint.setColorFilter(std::move(matrixFilter));
548 auto srcImageInfo =
surface->imageInfo();
550 return this->transferPixels(proxyView.proxy(),
562 std::fill_n(yM, 15, 0.f);
563 std::copy_n(baseM + 0, 5, yM + 15);
564 drawPlane(ySurface.
get(), srcImage, yM, texMatrix);
572 drawPlane(aSurface.
get(), srcImage,
nullptr, texMatrix);
578 std::fill_n(uM, 15, 0.f);
579 std::copy_n(baseM + 5, 5, uM + 15);
580 drawPlane(uSurface.
get(), srcImage, uM, texMatrix);
584 std::fill_n(vM, 15, 0.f);
585 std::copy_n(baseM + 10, 5, vM + 15);
586 drawPlane(vSurface.
get(), srcImage, vM, texMatrix);
589 std::unique_ptr<Recording> recording = recorder->
snap();
594 InsertRecordingInfo recordingInfo;
595 recordingInfo.fRecording = recording.get();
602 PixelTransferResult transfers[4];
603 transfers[0] = copyPlane(ySurface.
get());
604 if (!transfers[0].fTransferBuffer) {
608 transfers[1] = copyPlane(uSurface.
get());
609 if (!transfers[1].fTransferBuffer) {
613 transfers[2] = copyPlane(vSurface.
get());
614 if (!transfers[2].fTransferBuffer) {
619 transfers[3] = copyPlane(aSurface.
get());
620 if (!transfers[3].fTransferBuffer) {
626 this->finalizeAsyncReadPixels({transfers, readAlpha ? 4 : 3},
callback, callbackContext);
633 struct AsyncReadFinishContext {
636 ClientMappedBufferManager* fMappedBufferManager;
637 std::array<PixelTransferResult, 4> fTransferResults;
640 auto finishContext = std::make_unique<AsyncReadFinishContext>();
641 finishContext->fClientCallback =
callback;
642 finishContext->fClientContext = callbackContext;
643 finishContext->fMappedBufferManager = fMappedBufferManager.get();
645 SkASSERT(transferResults.
size() <= std::size(finishContext->fTransferResults));
647 for (
size_t i = 0; i < transferResults.
size(); ++i) {
648 finishContext->fTransferResults[i] = std::move(transferResults[i]);
649 if (fSharedContext->caps()->bufferMapsAreAsync()) {
650 buffersToAsyncMap.
push_back(finishContext->fTransferResults[i].fTransferBuffer);
654 InsertFinishInfo
info;
655 info.fFinishedContext = finishContext.release();
657 std::unique_ptr<const AsyncReadFinishContext> context(
658 reinterpret_cast<const AsyncReadFinishContext*
>(c));
661 ClientMappedBufferManager*
manager = context->fMappedBufferManager;
662 std::unique_ptr<AsyncReadResult>
result;
664 result = std::make_unique<AsyncReadResult>(
manager->ownerID());
666 for (
const auto& r : context->fTransferResults) {
667 if (!r.fTransferBuffer) {
670 if (
result && !
result->addTransferResult(r, r.fSize, r.fRowBytes, manager)) {
675 if (!
result && r.fTransferBuffer->isUnmappable()) {
676 r.fTransferBuffer->unmap();
679 (*context->fClientCallback)(context->fClientContext, std::move(
result));
685 if (!fQueueManager->addFinishInfo(
info, fResourceProvider.get(), buffersToAsyncMap)) {
686 SKGPU_LOG_E(
"Failed to register finish callbacks for asyncReadPixels.");
691Context::PixelTransferResult Context::transferPixels(
const TextureProxy* proxy,
697 const Caps* caps = fSharedContext->caps();
700 std::tie(supportedColorType, isRGB888Format) =
701 caps->supportedReadPixelsColorType(srcImageInfo.
colorType(),
702 proxy->textureInfo(),
713 if ((~legalReadChannels & dstChannels) & srcChannels) {
718 size_t rowBytes = caps->getAlignedTextureDataRowBytes(bpp * srcRect.
width());
719 size_t size =
SkAlignTo(rowBytes * srcRect.
height(), caps->requiredTransferBufferAlignment());
733 if (!copyTask || !fQueueManager->addTask(copyTask.
get(),
this)) {
737 if (!syncTask || !fQueueManager->addTask(syncTask.
get(),
this)) {
741 PixelTransferResult
result;
744 if (srcImageInfo.
colorInfo() != dstColorInfo || isRGB888Format) {
749 result.fPixelConverter = [dstInfo, srcInfo, rowBytes, isRGB888Format](
750 void*
dst,
const void*
src) {
752 size_t srcRowBytes = rowBytes;
753 if (isRGB888Format) {
756 auto* sRow =
reinterpret_cast<const char*
>(
src);
758 for (
int y = 0;
y < srcInfo.height(); ++
y, sRow += srcRowBytes, tRow += tRowBytes) {
759 for (
int x = 0;
x < srcInfo.width(); ++
x) {
761 auto t = tRow +
x*
sizeof(uint32_t);
763 t[3] =
static_cast<char>(0xFF);
767 srcRowBytes = tRowBytes;
770 srcInfo, src, srcRowBytes));
773 result.fRowBytes = rowBytes;
779void Context::checkForFinishedWork(
SyncToCpu syncToCpu) {
782 fQueueManager->checkForFinishedWork(syncToCpu);
783 fMappedBufferManager->process();
796 fResourceProvider->deleteBackendTexture(
texture);
804 fResourceProvider->freeGpuResources();
812 auto purgeTime = skgpu::StdSteadyClock::now() - msNotUsed;
813 fResourceProvider->purgeResourcesNotUsedSince(purgeTime);
818 return fResourceProvider->getResourceCacheCurrentBudgetedBytes();
823 return fResourceProvider->getResourceCacheLimit();
828 fResourceProvider->dumpMemoryStatistics(traceMemoryDump);
834 return fSharedContext->isDeviceLost();
838 return fSharedContext->caps()->maxTextureSize();
842 return fSharedContext->isProtected() == Protected::kYes;
847#if defined(GRAPHITE_TEST_UTILS)
848bool ContextPriv::readPixels(
const SkPixmap& pm,
851 int srcX,
int srcY) {
853 struct AsyncContext {
854 bool fCalled =
false;
855 std::unique_ptr<const SkImage::AsyncReadResult> fResult;
857 fContext->asyncReadPixels(textureProxy, srcImageInfo, pm.
info().
colorInfo(), rect,
858 [](
void* c, std::unique_ptr<const SkImage::AsyncReadResult>
result) {
859 auto context = static_cast<AsyncContext*>(c);
860 context->fResult = std::move(result);
861 context->fCalled = true;
865 if (fContext->fSharedContext->caps()->allowCpuSync()) {
870 while (!asyncContext.fCalled) {
872 auto dawnContext =
static_cast<DawnSharedContext*
>(fContext->fSharedContext.get());
873 dawnContext->device().Tick();
878 SK_ABORT(
"Only Dawn supports non-synching contexts.");
882 if (!asyncContext.fResult) {
891void ContextPriv::deregisterRecorder(
const Recorder* recorder) {
893 for (auto it = fContext->fTrackedRecorders.
begin();
894 it != fContext->fTrackedRecorders.
end();
896 if (*it == recorder) {
897 fContext->fTrackedRecorders.erase(it);
928 std::unique_ptr<QueueManager> queueManager,
930 auto context = std::unique_ptr<Context>(
new Context(std::move(sharedContext),
931 std::move(queueManager),
933 if (context && context->finishInitialization()) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#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)
#define SkAssertResult(cond)
#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 SkImage_Base * as_IB(SkImage *image)
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)
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])
const sk_sp< Effect > & get() const
void alloc(const SkImageInfo &)
void drawPaint(const SkPaint &paint)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
SkAlphaType alphaType() const
SkColorInfo makeColorType(SkColorType newColorType) const
SkColorSpace * colorSpace() const
SkColorType colorType() const
static bool Equals(const SkColorSpace *, const SkColorSpace *)
const SkImageInfo & imageInfo() 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
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)
std::unique_ptr< Recording > snap()
static sk_sp< Surface > Make(Recorder *recorder, const SkImageInfo &info, Budgeted budgeted, Mipmapped mipmapped=Mipmapped::kNo, SkBackingFit backingFit=SkBackingFit::kExact, const SkSurfaceProps *props=nullptr)
TextureProxyView readSurfaceView() const
static sk_sp< SynchronizeToCpuTask > Make(sk_sp< Buffer >)
Protected isProtected() const
TextureProxy * proxy() const
const TextureInfo & textureInfo() const
static const char * begin(const StringSlice &s)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static const uint8_t buffer[]
#define ASSERT_SINGLE_OWNER
SkSamplingOptions sampling
SK_API sk_sp< SkImage > AsImage(sk_sp< const SkSurface >)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
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
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 * GpuFinishedContext
constexpr int32_t x() const
constexpr int32_t y() const
constexpr SkISize size() const
constexpr int32_t height() const
int32_t fTop
smaller y-axis bounds
static constexpr SkIRect MakeSize(const SkISize &size)
constexpr int32_t width() const
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
int32_t fLeft
smaller x-axis bounds
bool contains(int32_t x, int32_t y) const
SkImageInfo makeWH(int newWidth, int newHeight) const
const SkColorInfo & colorInfo() const
size_t minRowBytes() const
SkImageInfo makeDimensions(SkISize newSize) const
SkISize dimensions() const
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkColorType colorType() const
static SkImageInfo MakeA8(int width, int height)
ContextOptionsPriv * fOptionsPriv
#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)