Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Protected Member Functions | Protected Attributes | Friends | List of all members
skgpu::ganesh::SurfaceContext Class Reference

#include <SurfaceContext.h>

Inheritance diagram for skgpu::ganesh::SurfaceContext:
skgpu::ganesh::SurfaceFillContext skgpu::ganesh::SurfaceDrawContext

Classes

struct  PixelTransferResult
 

Public Types

using ReadPixelsCallback = SkImage::ReadPixelsCallback
 
using ReadPixelsContext = SkImage::ReadPixelsContext
 
using RescaleGamma = SkImage::RescaleGamma
 
using RescaleMode = SkImage::RescaleMode
 

Public Member Functions

 SurfaceContext (GrRecordingContext *, GrSurfaceProxyView readView, const GrColorInfo &)
 
virtual ~SurfaceContext ()=default
 
GrRecordingContextrecordingContext () const
 
const GrColorInfocolorInfo () const
 
GrImageInfo imageInfo () const
 
GrSurfaceOrigin origin () const
 
skgpu::Swizzle readSwizzle () const
 
GrSurfaceProxyView readSurfaceView ()
 
SkISize dimensions () const
 
int width () const
 
int height () const
 
skgpu::Mipmapped mipmapped () const
 
const GrCapscaps () const
 
bool readPixels (GrDirectContext *dContext, GrPixmap dst, SkIPoint srcPt)
 
void asyncRescaleAndReadPixels (GrDirectContext *, const SkImageInfo &info, const SkIRect &srcRect, RescaleGamma rescaleGamma, RescaleMode, ReadPixelsCallback callback, ReadPixelsContext callbackContext)
 
void asyncRescaleAndReadPixelsYUV420 (GrDirectContext *, SkYUVColorSpace yuvColorSpace, bool readAlpha, sk_sp< SkColorSpace > dstColorSpace, const SkIRect &srcRect, SkISize dstSize, RescaleGamma rescaleGamma, RescaleMode, ReadPixelsCallback callback, ReadPixelsContext context)
 
bool writePixels (GrDirectContext *dContext, GrCPixmap src, SkIPoint dstPt)
 
bool writePixels (GrDirectContext *dContext, const GrCPixmap src[], int numLevels)
 
GrSurfaceProxyasSurfaceProxy ()
 
const GrSurfaceProxyasSurfaceProxy () const
 
sk_sp< GrSurfaceProxyasSurfaceProxyRef ()
 
GrTextureProxyasTextureProxy ()
 
const GrTextureProxyasTextureProxy () const
 
sk_sp< GrTextureProxyasTextureProxyRef ()
 
GrRenderTargetProxyasRenderTargetProxy ()
 
const GrRenderTargetProxyasRenderTargetProxy () const
 
sk_sp< GrRenderTargetProxyasRenderTargetProxyRef ()
 
virtual SurfaceFillContextasFillContext ()
 
std::unique_ptr< SurfaceFillContextrescale (const GrImageInfo &info, GrSurfaceOrigin, SkIRect srcRect, SkImage::RescaleGamma, SkImage::RescaleMode)
 
bool rescaleInto (SurfaceFillContext *dst, SkIRect dstRect, SkIRect srcRect, SkImage::RescaleGamma, SkImage::RescaleMode)
 

Protected Member Functions

GrDrawingManagerdrawingManager ()
 
const GrDrawingManagerdrawingManager () const
 
PixelTransferResult transferPixels (GrColorType colorType, const SkIRect &rect)
 
void asyncReadPixels (GrDirectContext *, const SkIRect &srcRect, SkColorType, ReadPixelsCallback, ReadPixelsContext)
 

Protected Attributes

SkDEBUGCODE(void validate() const ;) SkDEBUGCODE(skgpu GrRecordingContextfContext
 
GrSurfaceProxyView fReadView
 

Friends

class ::GrRecordingContextPriv
 
class ::GrSurfaceProxy
 

Detailed Description

Definition at line 42 of file SurfaceContext.h.

Member Typedef Documentation

◆ ReadPixelsCallback

Definition at line 78 of file SurfaceContext.h.

◆ ReadPixelsContext

Definition at line 79 of file SurfaceContext.h.

◆ RescaleGamma

Definition at line 80 of file SurfaceContext.h.

◆ RescaleMode

Definition at line 81 of file SurfaceContext.h.

Constructor & Destructor Documentation

◆ SurfaceContext()

skgpu::ganesh::SurfaceContext::SurfaceContext ( GrRecordingContext context,
GrSurfaceProxyView  readView,
const GrColorInfo info 
)

Definition at line 43 of file SurfaceContext.cpp.

46 : fContext(context), fReadView(std::move(readView)), fColorInfo(info) {
47 SkASSERT(!context->abandoned());
48}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
#define SkASSERT(cond)
Definition SkAssert.h:116
bool abandoned() override
SkDEBUGCODE(void validate() const ;) SkDEBUGCODE(skgpu GrRecordingContext * fContext

◆ ~SurfaceContext()

virtual skgpu::ganesh::SurfaceContext::~SurfaceContext ( )
virtualdefault

Member Function Documentation

◆ asFillContext()

virtual SurfaceFillContext * skgpu::ganesh::SurfaceContext::asFillContext ( )
inlinevirtual

Reimplemented in skgpu::ganesh::SurfaceFillContext.

Definition at line 141 of file SurfaceContext.h.

141{ return nullptr; }

◆ asRenderTargetProxy() [1/2]

GrRenderTargetProxy * skgpu::ganesh::SurfaceContext::asRenderTargetProxy ( )
inline

Definition at line 133 of file SurfaceContext.h.

133{ return fReadView.asRenderTargetProxy(); }
GrRenderTargetProxy * asRenderTargetProxy() const

◆ asRenderTargetProxy() [2/2]

const GrRenderTargetProxy * skgpu::ganesh::SurfaceContext::asRenderTargetProxy ( ) const
inline

Definition at line 134 of file SurfaceContext.h.

134 {
136 }

◆ asRenderTargetProxyRef()

sk_sp< GrRenderTargetProxy > skgpu::ganesh::SurfaceContext::asRenderTargetProxyRef ( )
inline

Definition at line 137 of file SurfaceContext.h.

137 {
139 }
sk_sp< GrRenderTargetProxy > asRenderTargetProxyRef() const

◆ asSurfaceProxy() [1/2]

GrSurfaceProxy * skgpu::ganesh::SurfaceContext::asSurfaceProxy ( )
inline

Definition at line 125 of file SurfaceContext.h.

125{ return fReadView.proxy(); }
GrSurfaceProxy * proxy() const

◆ asSurfaceProxy() [2/2]

const GrSurfaceProxy * skgpu::ganesh::SurfaceContext::asSurfaceProxy ( ) const
inline

Definition at line 126 of file SurfaceContext.h.

126{ return fReadView.proxy(); }

◆ asSurfaceProxyRef()

sk_sp< GrSurfaceProxy > skgpu::ganesh::SurfaceContext::asSurfaceProxyRef ( )
inline

Definition at line 127 of file SurfaceContext.h.

127{ return fReadView.refProxy(); }
sk_sp< GrSurfaceProxy > refProxy() const

◆ asTextureProxy() [1/2]

GrTextureProxy * skgpu::ganesh::SurfaceContext::asTextureProxy ( )
inline

Definition at line 129 of file SurfaceContext.h.

129{ return fReadView.asTextureProxy(); }
GrTextureProxy * asTextureProxy() const

◆ asTextureProxy() [2/2]

const GrTextureProxy * skgpu::ganesh::SurfaceContext::asTextureProxy ( ) const
inline

Definition at line 130 of file SurfaceContext.h.

130{ return fReadView.asTextureProxy(); }

◆ asTextureProxyRef()

sk_sp< GrTextureProxy > skgpu::ganesh::SurfaceContext::asTextureProxyRef ( )
inline

Definition at line 131 of file SurfaceContext.h.

131{ return fReadView.asTextureProxyRef(); }
sk_sp< GrTextureProxy > asTextureProxyRef() const

◆ asyncReadPixels()

void skgpu::ganesh::SurfaceContext::asyncReadPixels ( GrDirectContext dContext,
const SkIRect srcRect,
SkColorType  colorType,
ReadPixelsCallback  callback,
ReadPixelsContext  callbackContext 
)
protected

Definition at line 624 of file SurfaceContext.cpp.

628 {
630 PixelTransferResult>;
631
632 SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
633 SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
634
635 if (!dContext || this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
636 callback(callbackContext, nullptr);
637 return;
638 }
639
640 auto mappedBufferManager = dContext->priv().clientMappedBufferManager();
641
642 auto transferResult = this->transferPixels(SkColorTypeToGrColorType(colorType), rect);
643
644 if (!transferResult.fTransferBuffer) {
645 auto ii = SkImageInfo::Make(rect.size(), colorType, this->colorInfo().alphaType(),
646 this->colorInfo().refColorSpace());
648 auto result = std::make_unique<AsyncReadResult>(kInvalid);
650 result->addCpuPlane(pm.pixelStorage(), pm.rowBytes());
651
652 SkIPoint pt{rect.fLeft, rect.fTop};
653 if (!this->readPixels(dContext, pm, pt)) {
654 callback(callbackContext, nullptr);
655 return;
656 }
657 callback(callbackContext, std::move(result));
658 return;
659 }
660
661 struct FinishContext {
662 ReadPixelsCallback* fClientCallback;
663 ReadPixelsContext fClientContext;
664 SkISize fSize;
665 GrClientMappedBufferManager* fMappedBufferManager;
666 PixelTransferResult fTransferResult;
667 };
668 // Assumption is that the caller would like to flush. We could take a parameter or require an
669 // explicit flush from the caller. We'd have to have a way to defer attaching the finish
670 // callback to GrGpu until after the next flush that flushes our op list, though.
671 auto* finishContext = new FinishContext{callback,
672 callbackContext,
673 rect.size(),
674 mappedBufferManager,
675 std::move(transferResult)};
676 auto finishCallback = [](GrGpuFinishedContext c) {
677 const auto* context = reinterpret_cast<const FinishContext*>(c);
678 auto manager = context->fMappedBufferManager;
679 auto result = std::make_unique<AsyncReadResult>(manager->ownerID());
680 if (!result->addTransferResult(context->fTransferResult,
681 context->fSize,
682 context->fTransferResult.fRowBytes,
683 manager)) {
684 result.reset();
685 }
686 (*context->fClientCallback)(context->fClientContext, std::move(result));
687 delete context;
688 };
689 GrFlushInfo flushInfo;
690 flushInfo.fFinishedContext = finishContext;
691 flushInfo.fFinishedProc = finishCallback;
692
693 dContext->priv().flushSurface(
695}
static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct)
void * GrGpuFinishedContext
Definition GrTypes.h:178
@ kInvalid
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
GrSemaphoresSubmitted flushSurface(GrSurfaceProxy *proxy, SkSurfaces::BackendSurfaceAccess access=SkSurfaces::BackendSurfaceAccess::kNoAccess, const GrFlushInfo &info={}, const skgpu::MutableTextureState *newState=nullptr)
GrClientMappedBufferManager * clientMappedBufferManager()
GrDirectContextPriv priv()
sk_sp< SkData > pixelStorage() const
Definition GrPixmap.h:25
size_t rowBytes() const
Definition GrPixmap.h:21
static GrPixmap Allocate(const GrImageInfo &info)
Definition GrPixmap.h:101
PixelTransferResult transferPixels(GrColorType colorType, const SkIRect &rect)
GrSurfaceProxy * asSurfaceProxy()
bool readPixels(GrDirectContext *dContext, GrPixmap dst, SkIPoint srcPt)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
SkImage::ReadPixelsContext ReadPixelsContext
Definition Device.cpp:81
SkImage::ReadPixelsCallback ReadPixelsCallback
Definition Device.cpp:80
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
@ kNoAccess
back-end surface will not be used by client
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
Definition switches.h:218
GrGpuFinishedContext fFinishedContext
Definition GrTypes.h:220
GrGpuFinishedProc fFinishedProc
Definition GrTypes.h:219
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)

◆ asyncRescaleAndReadPixels()

void skgpu::ganesh::SurfaceContext::asyncRescaleAndReadPixels ( GrDirectContext dContext,
const SkImageInfo info,
const SkIRect srcRect,
RescaleGamma  rescaleGamma,
RescaleMode  rescaleMode,
ReadPixelsCallback  callback,
ReadPixelsContext  callbackContext 
)

Definition at line 553 of file SurfaceContext.cpp.

559 {
560 if (!dContext) {
561 callback(callbackContext, nullptr);
562 return;
563 }
564 auto rt = this->asRenderTargetProxy();
565 if (rt && rt->wrapsVkSecondaryCB()) {
566 callback(callbackContext, nullptr);
567 return;
568 }
569 if (rt && rt->framebufferOnly()) {
570 callback(callbackContext, nullptr);
571 return;
572 }
573 auto dstCT = SkColorTypeToGrColorType(info.colorType());
574 if (dstCT == GrColorType::kUnknown) {
575 callback(callbackContext, nullptr);
576 return;
577 }
578 bool needsRescale = srcRect.size() != info.dimensions() ||
580 this->colorInfo().alphaType() != info.alphaType() ||
581 !SkColorSpace::Equals(this->colorInfo().colorSpace(), info.colorSpace());
582 auto surfaceBackendFormat = this->asSurfaceProxy()->backendFormat();
583 auto readInfo = this->caps()->supportedReadPixelsColorType(this->colorInfo().colorType(),
584 surfaceBackendFormat,
585 dstCT);
586 // Fail if we can't read from the source surface's color type.
587 if (readInfo.fColorType == GrColorType::kUnknown) {
588 callback(callbackContext, nullptr);
589 return;
590 }
591 // Fail if read color type does not have all of dstCT's color channels and those missing color
592 // channels are in the src.
593 uint32_t dstChannels = GrColorTypeChannelFlags(dstCT);
594 uint32_t legalReadChannels = GrColorTypeChannelFlags(readInfo.fColorType);
595 uint32_t srcChannels = GrColorTypeChannelFlags(this->colorInfo().colorType());
596 if ((~legalReadChannels & dstChannels) & srcChannels) {
597 callback(callbackContext, nullptr);
598 return;
599 }
600
601 std::unique_ptr<SurfaceFillContext> tempFC;
602 int x = srcRect.fLeft;
603 int y = srcRect.fTop;
604 if (needsRescale) {
605 auto tempInfo = GrImageInfo(info).makeColorType(this->colorInfo().colorType());
606 tempFC = this->rescale(tempInfo, kTopLeft_GrSurfaceOrigin, srcRect,
607 rescaleGamma, rescaleMode);
608 if (!tempFC) {
609 callback(callbackContext, nullptr);
610 return;
611 }
612 SkASSERT(SkColorSpace::Equals(tempFC->colorInfo().colorSpace(), info.colorSpace()));
613 SkASSERT(tempFC->origin() == kTopLeft_GrSurfaceOrigin);
614 x = y = 0;
615 }
616 auto srcCtx = tempFC ? tempFC.get() : this;
617 return srcCtx->asyncReadPixels(dContext,
618 SkIRect::MakePtSize({x, y}, info.dimensions()),
619 info.colorType(),
620 callback,
621 callbackContext);
622}
static constexpr uint32_t GrColorTypeChannelFlags(GrColorType ct)
@ kBottomLeft_GrSurfaceOrigin
Definition GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
SupportedRead supportedReadPixelsColorType(GrColorType srcColorType, const GrBackendFormat &srcFormat, GrColorType dstColorType) const
Definition GrCaps.cpp:366
SkColorSpace * colorSpace() const
SkAlphaType alphaType() const
Definition GrColorInfo.h:44
GrImageInfo makeColorType(GrColorType ct) const
const GrBackendFormat & backendFormat() const
static bool Equals(const SkColorSpace *, const SkColorSpace *)
GrRenderTargetProxy * asRenderTargetProxy()
const GrCaps * caps() const
const GrColorInfo & colorInfo() const
std::unique_ptr< SurfaceFillContext > rescale(const GrImageInfo &info, GrSurfaceOrigin, SkIRect srcRect, SkImage::RescaleGamma, SkImage::RescaleMode)
GrSurfaceOrigin origin() const
double y
double x
constexpr SkISize size() const
Definition SkRect.h:172
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size)
Definition SkRect.h:78
SkAlphaType alphaType() const

◆ asyncRescaleAndReadPixelsYUV420()

void skgpu::ganesh::SurfaceContext::asyncRescaleAndReadPixelsYUV420 ( GrDirectContext dContext,
SkYUVColorSpace  yuvColorSpace,
bool  readAlpha,
sk_sp< SkColorSpace dstColorSpace,
const SkIRect srcRect,
SkISize  dstSize,
RescaleGamma  rescaleGamma,
RescaleMode  rescaleMode,
ReadPixelsCallback  callback,
ReadPixelsContext  context 
)

Definition at line 697 of file SurfaceContext.cpp.

706 {
708 PixelTransferResult>;
709
710 SkASSERT(srcRect.fLeft >= 0 && srcRect.fRight <= this->width());
711 SkASSERT(srcRect.fTop >= 0 && srcRect.fBottom <= this->height());
712 SkASSERT(!dstSize.isZero());
713 SkASSERT((dstSize.width() % 2 == 0) && (dstSize.height() % 2 == 0));
714
715 if (!dContext) {
716 callback(callbackContext, nullptr);
717 return;
718 }
719 auto rt = this->asRenderTargetProxy();
720 if (rt && rt->wrapsVkSecondaryCB()) {
721 callback(callbackContext, nullptr);
722 return;
723 }
724 if (rt && rt->framebufferOnly()) {
725 callback(callbackContext, nullptr);
726 return;
727 }
728 if (this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
729 callback(callbackContext, nullptr);
730 return;
731 }
732 int x = srcRect.fLeft;
733 int y = srcRect.fTop;
734 bool needsRescale = srcRect.size() != dstSize ||
735 !SkColorSpace::Equals(this->colorInfo().colorSpace(), dstColorSpace.get());
736 GrSurfaceProxyView srcView = this->readSurfaceView();
737 if (needsRescale) {
738 auto info = SkImageInfo::Make(dstSize,
740 this->colorInfo().alphaType(),
741 dstColorSpace);
742 // TODO: Incorporate the YUV conversion into last pass of rescaling.
743 auto tempFC = this->rescale(info,
745 srcRect,
746 rescaleGamma,
747 rescaleMode);
748 if (!tempFC) {
749 callback(callbackContext, nullptr);
750 return;
751 }
752 SkASSERT(SkColorSpace::Equals(tempFC->colorInfo().colorSpace(), info.colorSpace()));
753 SkASSERT(tempFC->origin() == kTopLeft_GrSurfaceOrigin);
754 x = y = 0;
755 srcView = tempFC->readSurfaceView();
756 } else if (!srcView.asTextureProxy()) {
757 srcView = GrSurfaceProxyView::Copy(
758 fContext,
759 std::move(srcView),
760 skgpu::Mipmapped::kNo,
761 srcRect,
764 /*label=*/"SurfaceContext_AsyncRescaleAndReadPixelsYUV420");
765 if (!srcView) {
766 // If we can't get a texture copy of the contents then give up.
767 callback(callbackContext, nullptr);
768 return;
769 }
770 SkASSERT(srcView.asTextureProxy());
771 x = y = 0;
772 }
773
774 auto yaInfo = SkImageInfo::MakeA8(dstSize);
775 auto yFC = dContext->priv().makeSFCWithFallback(yaInfo, SkBackingFit::kApprox,
776 /* sampleCount= */ 1,
777 skgpu::Mipmapped::kNo, skgpu::Protected::kNo);
778 std::unique_ptr<SurfaceFillContext> aFC;
779 if (readAlpha) {
780 aFC = dContext->priv().makeSFCWithFallback(yaInfo, SkBackingFit::kApprox,
781 /* sampleCount= */ 1,
782 skgpu::Mipmapped::kNo, skgpu::Protected::kNo);
783 }
784
785 auto uvInfo = yaInfo.makeWH(yaInfo.width()/2, yaInfo.height()/2);
786 auto uFC = dContext->priv().makeSFCWithFallback(uvInfo, SkBackingFit::kApprox,
787 /* sampleCount= */ 1,
788 skgpu::Mipmapped::kNo, skgpu::Protected::kNo);
789 auto vFC = dContext->priv().makeSFCWithFallback(uvInfo, SkBackingFit::kApprox,
790 /* sampleCount= */ 1,
791 skgpu::Mipmapped::kNo, skgpu::Protected::kNo);
792
793 if (!yFC || !uFC || !vFC || (readAlpha && !aFC)) {
794 callback(callbackContext, nullptr);
795 return;
796 }
797
798 float baseM[20];
799 SkColorMatrix_RGB2YUV(yuvColorSpace, baseM);
800
801 // TODO: Use one transfer buffer for all three planes to reduce map/unmap cost?
802
803 auto texMatrix = SkMatrix::Translate(x, y);
804
805 auto [readCT, offsetAlignment] =
806 this->caps()->supportedReadPixelsColorType(yFC->colorInfo().colorType(),
807 yFC->asSurfaceProxy()->backendFormat(),
809 if (readCT == GrColorType::kUnknown) {
810 callback(callbackContext, nullptr);
811 return;
812 }
813 bool doSynchronousRead = !this->caps()->transferFromSurfaceToBufferSupport() ||
814 !offsetAlignment;
815 PixelTransferResult yTransfer, aTransfer, uTransfer, vTransfer;
816
817 // This matrix generates (r,g,b,a) = (0, 0, 0, y)
818 float yM[20];
819 std::fill_n(yM, 15, 0.f);
820 std::copy_n(baseM + 0, 5, yM + 15);
821
822 auto yFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix);
823 yFP = GrFragmentProcessor::ColorMatrix(std::move(yFP),
824 yM,
825 /*unpremulInput=*/false,
826 /*clampRGBOutput=*/true,
827 /*premulOutput=*/false);
828 yFC->fillWithFP(std::move(yFP));
829 if (!doSynchronousRead) {
830 yTransfer = yFC->transferPixels(GrColorType::kAlpha_8,
831 SkIRect::MakeSize(yFC->dimensions()));
832 if (!yTransfer.fTransferBuffer) {
833 callback(callbackContext, nullptr);
834 return;
835 }
836 }
837
838 if (readAlpha) {
839 auto aFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix);
840 SkASSERT(baseM[15] == 0 &&
841 baseM[16] == 0 &&
842 baseM[17] == 0 &&
843 baseM[18] == 1 &&
844 baseM[19] == 0);
845 aFC->fillWithFP(std::move(aFP));
846 if (!doSynchronousRead) {
847 aTransfer = aFC->transferPixels(GrColorType::kAlpha_8,
848 SkIRect::MakeSize(aFC->dimensions()));
849 if (!aTransfer.fTransferBuffer) {
850 callback(callbackContext, nullptr);
851 return;
852 }
853 }
854 }
855
856 texMatrix.preScale(2.f, 2.f);
857 // This matrix generates (r,g,b,a) = (0, 0, 0, u)
858 float uM[20];
859 std::fill_n(uM, 15, 0.f);
860 std::copy_n(baseM + 5, 5, uM + 15);
861
862 auto uFP = GrTextureEffect::Make(srcView,
863 this->colorInfo().alphaType(),
864 texMatrix,
865 GrSamplerState::Filter::kLinear);
866 uFP = GrFragmentProcessor::ColorMatrix(std::move(uFP),
867 uM,
868 /*unpremulInput=*/false,
869 /*clampRGBOutput=*/true,
870 /*premulOutput=*/false);
871 uFC->fillWithFP(std::move(uFP));
872 if (!doSynchronousRead) {
873 uTransfer = uFC->transferPixels(GrColorType::kAlpha_8,
874 SkIRect::MakeSize(uFC->dimensions()));
875 if (!uTransfer.fTransferBuffer) {
876 callback(callbackContext, nullptr);
877 return;
878 }
879 }
880
881 // This matrix generates (r,g,b,a) = (0, 0, 0, v)
882 float vM[20];
883 std::fill_n(vM, 15, 0.f);
884 std::copy_n(baseM + 10, 5, vM + 15);
885 auto vFP = GrTextureEffect::Make(std::move(srcView),
886 this->colorInfo().alphaType(),
887 texMatrix,
888 GrSamplerState::Filter::kLinear);
889 vFP = GrFragmentProcessor::ColorMatrix(std::move(vFP),
890 vM,
891 /*unpremulInput=*/false,
892 /*clampRGBOutput=*/true,
893 /*premulOutput=*/false);
894 vFC->fillWithFP(std::move(vFP));
895
896 if (!doSynchronousRead) {
897 vTransfer = vFC->transferPixels(GrColorType::kAlpha_8,
898 SkIRect::MakeSize(vFC->dimensions()));
899 if (!vTransfer.fTransferBuffer) {
900 callback(callbackContext, nullptr);
901 return;
902 }
903 }
904
905 if (doSynchronousRead) {
906 GrPixmap yPmp = GrPixmap::Allocate(yaInfo);
907 GrPixmap uPmp = GrPixmap::Allocate(uvInfo);
908 GrPixmap vPmp = GrPixmap::Allocate(uvInfo);
909 GrPixmap aPmp;
910 if (readAlpha) {
911 aPmp = GrPixmap::Allocate(yaInfo);
912 }
913 if (!yFC->readPixels(dContext, yPmp, {0, 0}) ||
914 !uFC->readPixels(dContext, uPmp, {0, 0}) ||
915 !vFC->readPixels(dContext, vPmp, {0, 0}) ||
916 (readAlpha && !aFC->readPixels(dContext, aPmp, {0, 0}))) {
917 callback(callbackContext, nullptr);
918 return;
919 }
920 auto result = std::make_unique<AsyncReadResult>(dContext->directContextID());
921 result->addCpuPlane(yPmp.pixelStorage(), yPmp.rowBytes());
922 result->addCpuPlane(uPmp.pixelStorage(), uPmp.rowBytes());
923 result->addCpuPlane(vPmp.pixelStorage(), vPmp.rowBytes());
924 if (readAlpha) {
925 result->addCpuPlane(aPmp.pixelStorage(), aPmp.rowBytes());
926 }
927 callback(callbackContext, std::move(result));
928 return;
929 }
930
931 struct FinishContext {
932 ReadPixelsCallback* fClientCallback;
933 ReadPixelsContext fClientContext;
934 GrClientMappedBufferManager* fMappedBufferManager;
935 SkISize fSize;
936 PixelTransferResult fYTransfer;
937 PixelTransferResult fUTransfer;
938 PixelTransferResult fVTransfer;
939 PixelTransferResult fATransfer;
940 };
941 // Assumption is that the caller would like to flush. We could take a parameter or require an
942 // explicit flush from the caller. We'd have to have a way to defer attaching the finish
943 // callback to GrGpu until after the next flush that flushes our op list, though.
944 auto* finishContext = new FinishContext{callback,
945 callbackContext,
946 dContext->priv().clientMappedBufferManager(),
947 dstSize,
948 std::move(yTransfer),
949 std::move(uTransfer),
950 std::move(vTransfer),
951 std::move(aTransfer)};
952 auto finishCallback = [](GrGpuFinishedContext c) {
953 const auto* context = reinterpret_cast<const FinishContext*>(c);
954 auto manager = context->fMappedBufferManager;
955 auto result = std::make_unique<AsyncReadResult>(manager->ownerID());
956 if (!result->addTransferResult(context->fYTransfer,
957 context->fSize,
958 context->fYTransfer.fRowBytes,
959 manager)) {
960 (*context->fClientCallback)(context->fClientContext, nullptr);
961 delete context;
962 return;
963 }
964 SkISize uvSize = {context->fSize.width() / 2, context->fSize.height() / 2};
965 if (!result->addTransferResult(context->fUTransfer,
966 uvSize,
967 context->fUTransfer.fRowBytes,
968 manager)) {
969 (*context->fClientCallback)(context->fClientContext, nullptr);
970 delete context;
971 return;
972 }
973 if (!result->addTransferResult(context->fVTransfer,
974 uvSize,
975 context->fVTransfer.fRowBytes,
976 manager)) {
977 (*context->fClientCallback)(context->fClientContext, nullptr);
978 delete context;
979 return;
980 }
981 if (context->fATransfer.fTransferBuffer &&
982 !result->addTransferResult(context->fATransfer,
983 context->fSize,
984 context->fATransfer.fRowBytes,
985 manager)) {
986 (*context->fClientCallback)(context->fClientContext, nullptr);
987 delete context;
988 return;
989 }
990 (*context->fClientCallback)(context->fClientContext, std::move(result));
991 delete context;
992 };
993 GrFlushInfo flushInfo;
994 flushInfo.fFinishedContext = finishContext;
995 flushInfo.fFinishedProc = finishCallback;
996 dContext->priv().flushSurface(
998}
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
void SkColorMatrix_RGB2YUV(SkYUVColorSpace cs, float m[20])
bool transferFromSurfaceToBufferSupport() const
Definition GrCaps.h:367
DirectContextID directContextID() const
static std::unique_ptr< GrFragmentProcessor > ColorMatrix(std::unique_ptr< GrFragmentProcessor > child, const float matrix[20], bool unpremulInput, bool clampRGBOutput, bool premulOutput)
std::unique_ptr< skgpu::ganesh::SurfaceFillContext > makeSFCWithFallback(GrImageInfo, SkBackingFit, int sampleCount, skgpu::Mipmapped, skgpu::Protected, GrSurfaceOrigin=kTopLeft_GrSurfaceOrigin, skgpu::Budgeted=skgpu::Budgeted::kYes)
static GrSurfaceProxyView Copy(GrRecordingContext *context, GrSurfaceProxyView src, skgpu::Mipmapped mipmapped, SkIRect srcRect, SkBackingFit fit, skgpu::Budgeted budgeted, std::string_view label)
static std::unique_ptr< GrFragmentProcessor > Make(GrSurfaceProxyView, SkAlphaType, const SkMatrix &=SkMatrix::I(), GrSamplerState::Filter=GrSamplerState::Filter::kNearest, GrSamplerState::MipmapMode mipmapMode=GrSamplerState::MipmapMode::kNone)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition SkMatrix.h:91
T * get() const
Definition SkRefCnt.h:303
GrSurfaceProxyView readSurfaceView()
int32_t fBottom
larger y-axis bounds
Definition SkRect.h:36
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
int32_t fRight
larger x-axis bounds
Definition SkRect.h:35
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
bool isZero() const
Definition SkSize.h:28
static SkImageInfo MakeA8(int width, int height)

◆ caps()

const GrCaps * skgpu::ganesh::SurfaceContext::caps ( ) const

Definition at line 50 of file SurfaceContext.cpp.

50{ return fContext->priv().caps(); }
const GrCaps * caps() const
GrRecordingContextPriv priv()

◆ colorInfo()

const GrColorInfo & skgpu::ganesh::SurfaceContext::colorInfo ( ) const
inline

Definition at line 52 of file SurfaceContext.h.

52{ return fColorInfo; }

◆ dimensions()

SkISize skgpu::ganesh::SurfaceContext::dimensions ( ) const
inline

Definition at line 61 of file SurfaceContext.h.

61{ return fReadView.dimensions(); }
SkISize dimensions() const

◆ drawingManager() [1/2]

GrDrawingManager * skgpu::ganesh::SurfaceContext::drawingManager ( )
protected

Definition at line 52 of file SurfaceContext.cpp.

52 {
53 return fContext->priv().drawingManager();
54}
GrDrawingManager * drawingManager()

◆ drawingManager() [2/2]

const GrDrawingManager * skgpu::ganesh::SurfaceContext::drawingManager ( ) const
protected

Definition at line 56 of file SurfaceContext.cpp.

56 {
57 return fContext->priv().drawingManager();
58}

◆ height()

int skgpu::ganesh::SurfaceContext::height ( ) const
inline

Definition at line 63 of file SurfaceContext.h.

63{ return fReadView.proxy()->height(); }
int height() const

◆ imageInfo()

GrImageInfo skgpu::ganesh::SurfaceContext::imageInfo ( ) const
inline

Definition at line 53 of file SurfaceContext.h.

53{ return {fColorInfo, fReadView.proxy()->dimensions()}; }
SkISize dimensions() const

◆ mipmapped()

skgpu::Mipmapped skgpu::ganesh::SurfaceContext::mipmapped ( ) const
inline

Definition at line 65 of file SurfaceContext.h.

65{ return fReadView.mipmapped(); }
skgpu::Mipmapped mipmapped() const

◆ origin()

GrSurfaceOrigin skgpu::ganesh::SurfaceContext::origin ( ) const
inline

Definition at line 55 of file SurfaceContext.h.

55{ return fReadView.origin(); }
GrSurfaceOrigin origin() const

◆ readPixels()

bool skgpu::ganesh::SurfaceContext::readPixels ( GrDirectContext dContext,
GrPixmap  dst,
SkIPoint  srcPt 
)

Reads a rectangle of pixels from the surface context.

Parameters
dContextThe direct context to use
dstdestination pixels for the read
srcPtoffset w/in the surface context from which to read is a GrDirectContext and fail otherwise.

Definition at line 69 of file SurfaceContext.cpp.

69 {
72 SkDEBUGCODE(this->validate();)
73 GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceContext", "readPixels", fContext);
74
75 if (!fContext->priv().matches(dContext)) {
76 return false;
77 }
78
79 if (dst.colorType() == GrColorType::kUnknown) {
80 return false;
81 }
82
83 if (dst.rowBytes() % dst.info().bpp()) {
84 return false;
85 }
86
87 dst = dst.clip(this->dimensions(), &pt);
88 if (!dst.hasPixels()) {
89 return false;
90 }
91 if (!alpha_types_compatible(this->colorInfo().alphaType(), dst.alphaType())) {
92 return false;
93 }
94 // We allow unknown alpha types but only if both src and dst are unknown. Otherwise, it's too
95 // weird to reason about what should be expected.
96
98
99 if (srcProxy->framebufferOnly()) {
100 return false;
101 }
102
103 // MDB TODO: delay this instantiation until later in the method
104 if (!srcProxy->instantiate(dContext->priv().resourceProvider())) {
105 return false;
106 }
107
108 GrSurface* srcSurface = srcProxy->peekSurface();
109
111 SkColorSpaceXformSteps{this->colorInfo(), dst.info()}.flags;
112 bool unpremul = flags.unpremul,
113 needColorConversion = flags.linearize || flags.gamut_transform || flags.encode,
114 premul = flags.premul;
115
116 const GrCaps* caps = dContext->priv().caps();
117 bool srcIsCompressed = caps->isFormatCompressed(srcSurface->backendFormat());
118 // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
119 // care so much about getImageData performance. However, in order to ensure putImageData/
120 // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
121 // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
122 // fContext->vaildaPMUPMConversionExists()).
124 GrRenderable::kYes);
125 GrColorType srcColorType = this->colorInfo().colorType();
126 bool canvas2DFastPath = unpremul && !needColorConversion &&
127 (GrColorType::kRGBA_8888 == dst.colorType() ||
128 GrColorType::kBGRA_8888 == dst.colorType()) &&
129 SkToBool(srcProxy->asTextureProxy()) &&
130 (srcColorType == GrColorType::kRGBA_8888 ||
131 srcColorType == GrColorType::kBGRA_8888) &&
132 defaultRGBAFormat.isValid() &&
133 dContext->priv().validPMUPMConversionExists();
134
135 // Since the validPMUPMConversionExists function actually submits work to the gpu to do its
136 // tests, it is possible that during that call we have abandoned the context. Thus, we do
137 // another abandoned check here to make sure we are still valid.
139
140 auto readFlag = caps->surfaceSupportsReadPixels(srcSurface);
142 return false;
143 }
144
145 if (readFlag == GrCaps::SurfaceReadPixelsSupport::kCopyToTexture2D || canvas2DFastPath) {
146 std::unique_ptr<SurfaceContext> tempCtx;
147 if (this->asTextureProxy()) {
148 GrColorType colorType = (canvas2DFastPath || srcIsCompressed)
150 : this->colorInfo().colorType();
151 SkAlphaType alphaType = canvas2DFastPath ? dst.alphaType()
152 : this->colorInfo().alphaType();
153 GrImageInfo tempInfo(colorType,
154 alphaType,
155 this->colorInfo().refColorSpace(),
156 dst.dimensions());
157 auto sfc = dContext->priv().makeSFC(
158 tempInfo, "SurfaceContext_ReadPixels", SkBackingFit::kApprox);
159 if (!sfc) {
160 return false;
161 }
162
163 std::unique_ptr<GrFragmentProcessor> fp;
164 if (canvas2DFastPath) {
166 this->readSurfaceView(), this->colorInfo().alphaType()));
167 if (dst.colorType() == GrColorType::kBGRA_8888) {
169 dst = GrPixmap(dst.info().makeColorType(GrColorType::kRGBA_8888),
170 dst.addr(),
171 dst.rowBytes());
172 }
173 } else {
174 fp = GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType());
175 }
176 if (!fp) {
177 return false;
178 }
179 sfc->fillRectToRectWithFP(SkIRect::MakePtSize(pt, dst.dimensions()),
180 SkIRect::MakeSize(dst.dimensions()),
181 std::move(fp));
182 pt = {0, 0};
183 tempCtx = std::move(sfc);
184 } else {
185 auto restrictions = this->caps()->getDstCopyRestrictions(this->asRenderTargetProxy(),
186 this->colorInfo().colorType());
188 static constexpr auto kFit = SkBackingFit::kExact;
189 static constexpr auto kBudgeted = skgpu::Budgeted::kYes;
190 static constexpr auto kMipMapped = skgpu::Mipmapped::kNo;
191 if (restrictions.fMustCopyWholeSrc) {
193 std::move(srcProxy),
194 this->origin(),
195 kMipMapped,
196 kFit,
197 kBudgeted,
198 /*label=*/"SurfaceContext_ReadPixelsWithCopyWholeSrc");
199 } else {
200 auto srcRect = SkIRect::MakePtSize(pt, dst.dimensions());
202 std::move(srcProxy),
203 this->origin(),
204 kMipMapped,
205 srcRect,
206 kFit,
207 kBudgeted,
208 /*label=*/"SurfaceContext_ReadPixels",
209 restrictions.fRectsMustMatch);
210 pt = {0, 0};
211 }
212 if (!copy) {
213 return false;
214 }
215 GrSurfaceProxyView view{std::move(copy), this->origin(), this->readSwizzle()};
216 tempCtx = dContext->priv().makeSC(std::move(view), this->colorInfo());
217 SkASSERT(tempCtx);
218 }
219 return tempCtx->readPixels(dContext, dst, pt);
220 }
221
222 bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
223
224 auto supportedRead = caps->supportedReadPixelsColorType(
225 this->colorInfo().colorType(), srcProxy->backendFormat(), dst.colorType());
226
227 bool makeTight =
228 !caps->readPixelsRowBytesSupport() && dst.rowBytes() != dst.info().minRowBytes();
229
230 bool convert = unpremul || premul || needColorConversion || flip || makeTight ||
231 (dst.colorType() != supportedRead.fColorType);
232
233 std::unique_ptr<char[]> tmpPixels;
234 GrPixmap tmp;
235 void* readDst = dst.addr();
236 size_t readRB = dst.rowBytes();
237 if (convert) {
238 GrImageInfo tmpInfo(supportedRead.fColorType,
239 this->colorInfo().alphaType(),
240 this->colorInfo().refColorSpace(),
241 dst.dimensions());
242 size_t tmpRB = tmpInfo.minRowBytes();
243 size_t size = tmpRB * tmpInfo.height();
244 // Chrome MSAN bots require the data to be initialized (hence the ()).
245 tmpPixels = std::make_unique<char[]>(size);
246 tmp = {tmpInfo, tmpPixels.get(), tmpRB};
247
248 readDst = tmpPixels.get();
249 readRB = tmpRB;
250 pt.fY = flip ? srcSurface->height() - pt.fY - dst.height() : pt.fY;
251 }
252
253 dContext->priv().flushSurface(srcProxy.get());
254 dContext->submit();
255 if (!dContext->priv().getGpu()->readPixels(srcSurface,
256 SkIRect::MakePtSize(pt, dst.dimensions()),
257 this->colorInfo().colorType(),
258 supportedRead.fColorType,
259 readDst,
260 readRB)) {
261 return false;
262 }
263
264 if (tmp.hasPixels()) {
265 return GrConvertPixels(dst, tmp, flip);
266 }
267 return true;
268}
bool GrConvertPixels(const GrPixmap &dst, const GrCPixmap &src, bool flipY)
#define GR_CREATE_TRACE_MARKER_CONTEXT(classname, op, context)
Definition GrTracing.h:18
GrColorType
SkAlphaType
Definition SkAlphaType.h:26
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
#define RETURN_FALSE_IF_ABANDONED
static uint32_t premul(uint32_t color)
bool isValid() const
bool matches(GrContext_Base *candidate) const
virtual SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface *) const =0
virtual DstCopyRestrictions getDstCopyRestrictions(const GrRenderTargetProxy *src, GrColorType ct) const
Definition GrCaps.h:461
GrBackendFormat getDefaultBackendFormat(GrColorType, GrRenderable) const
Definition GrCaps.cpp:400
bool isFormatCompressed(const GrBackendFormat &format) const
Definition GrCaps.cpp:457
bool readPixelsRowBytesSupport() const
Definition GrCaps.h:365
GrColorType colorType() const
Definition GrColorInfo.h:43
GrResourceProvider * resourceProvider()
std::unique_ptr< GrFragmentProcessor > createPMToUPMEffect(std::unique_ptr< GrFragmentProcessor >)
bool submit(GrSyncCpu sync=GrSyncCpu::kNo)
static std::unique_ptr< GrFragmentProcessor > SwizzleOutput(std::unique_ptr< GrFragmentProcessor >, const skgpu::Swizzle &)
bool readPixels(GrSurface *surface, SkIRect rect, GrColorType surfaceColorType, GrColorType dstColorType, void *buffer, size_t rowBytes)
Definition GrGpu.cpp:426
const GrImageInfo & info() const
Definition GrPixmap.h:17
bool hasPixels() const
Definition GrPixmap.h:23
std::unique_ptr< skgpu::ganesh::SurfaceContext > makeSC(GrSurfaceProxyView readView, const GrColorInfo &)
std::unique_ptr< skgpu::ganesh::SurfaceFillContext > makeSFC(GrImageInfo, std::string_view label, SkBackingFit=SkBackingFit::kExact, int sampleCount=1, skgpu::Mipmapped=skgpu::Mipmapped::kNo, skgpu::Protected=skgpu::Protected::kNo, GrSurfaceOrigin=kTopLeft_GrSurfaceOrigin, skgpu::Budgeted=skgpu::Budgeted::kYes)
static sk_sp< GrSurfaceProxy > Copy(GrRecordingContext *, sk_sp< GrSurfaceProxy > src, GrSurfaceOrigin, skgpu::Mipmapped, SkIRect srcRect, SkBackingFit, skgpu::Budgeted, std::string_view label, RectsMustMatch=RectsMustMatch::kNo, sk_sp< GrRenderTask > *outTask=nullptr)
virtual GrBackendFormat backendFormat() const =0
int height() const
Definition GrSurface.h:37
static constexpr Swizzle BGRA()
Definition Swizzle.h:67
GrTextureProxy * asTextureProxy()
skgpu::Swizzle readSwizzle() const
sk_sp< GrSurfaceProxy > asSurfaceProxyRef()
static Editor::Movement convert(skui::Key key)
FlutterSemanticsFlag flags
#define ASSERT_SINGLE_OWNER
Definition Device.cpp:120
Definition copy.py:1
const uint32_t fp
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
Definition switches.h:259
dst
Definition cp.py:12
static bool alpha_types_compatible(SkAlphaType srcAlphaType, SkAlphaType dstAlphaType)

◆ readSurfaceView()

GrSurfaceProxyView skgpu::ganesh::SurfaceContext::readSurfaceView ( )
inline

Definition at line 59 of file SurfaceContext.h.

59{ return fReadView; }

◆ readSwizzle()

skgpu::Swizzle skgpu::ganesh::SurfaceContext::readSwizzle ( ) const
inline

Definition at line 56 of file SurfaceContext.h.

56{ return fReadView.swizzle(); }
skgpu::Swizzle swizzle() const

◆ recordingContext()

GrRecordingContext * skgpu::ganesh::SurfaceContext::recordingContext ( ) const
inline

Definition at line 50 of file SurfaceContext.h.

50{ return fContext; }

◆ rescale()

std::unique_ptr< SurfaceFillContext > skgpu::ganesh::SurfaceContext::rescale ( const GrImageInfo info,
GrSurfaceOrigin  origin,
SkIRect  srcRect,
SkImage::RescaleGamma  rescaleGamma,
SkImage::RescaleMode  rescaleMode 
)

Rescales the contents of srcRect. The gamma in which the rescaling occurs is controlled by RescaleGamma. It is always in the original gamut. The result is converted to the color type and color space of info after rescaling. Note: this currently requires that the info have a different size than srcRect. Though, it could be relaxed to allow non-scaling color conversions.

Definition at line 1081 of file SurfaceContext.cpp.

1085 {
1086 auto sfc = fContext->priv().makeSFCWithFallback(info,
1088 /* sampleCount= */ 1,
1089 skgpu::Mipmapped::kNo,
1090 this->asSurfaceProxy()->isProtected(),
1091 origin);
1092 if (!sfc || !this->rescaleInto(sfc.get(),
1093 SkIRect::MakeSize(sfc->dimensions()),
1094 srcRect,
1095 rescaleGamma,
1096 rescaleMode)) {
1097 return nullptr;
1098 }
1099 return sfc;
1100}
bool rescaleInto(SurfaceFillContext *dst, SkIRect dstRect, SkIRect srcRect, SkImage::RescaleGamma, SkImage::RescaleMode)

◆ rescaleInto()

bool skgpu::ganesh::SurfaceContext::rescaleInto ( SurfaceFillContext dst,
SkIRect  dstRect,
SkIRect  srcRect,
SkImage::RescaleGamma  rescaleGamma,
SkImage::RescaleMode  rescaleMode 
)

Like the above but allows the caller ot specify a destination fill context and rect within that context. The dst rect must be contained by the dst or this will fail.

Definition at line 1102 of file SurfaceContext.cpp.

1106 {
1107 SkASSERT(dst);
1108 if (!SkIRect::MakeSize(dst->dimensions()).contains((dstRect))) {
1109 return false;
1110 }
1111
1112 auto rtProxy = this->asRenderTargetProxy();
1113 if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
1114 return false;
1115 }
1116
1117 if (this->asSurfaceProxy()->framebufferOnly()) {
1118 return false;
1119 }
1120
1121 GrSurfaceProxyView texView = this->readSurfaceView();
1122 // If we perform scaling as draws, texView must be texturable; if it's not already, we have to
1123 // make a copy. However, if the scaling can use copyScaled(), we can avoid this copy.
1124 auto ensureTexturable = [this](GrSurfaceProxyView texView, SkIRect srcRect) {
1125 if (!texView.asTextureProxy()) {
1126 // TODO: If copying supported specifying a renderable copy then we could return the copy
1127 // when there are no other conversions.
1129 std::move(texView),
1130 skgpu::Mipmapped::kNo,
1131 srcRect,
1134 "SurfaceContext_RescaleInto");
1135 if (texView) {
1136 SkASSERT(texView.asTextureProxy());
1137 srcRect = SkIRect::MakeSize(srcRect.size());
1138 }
1139 }
1140 return std::make_pair(std::move(texView), srcRect);
1141 };
1142
1143 SkISize finalSize = dstRect.size();
1144 if (finalSize == srcRect.size()) {
1145 rescaleGamma = RescaleGamma::kSrc;
1146 rescaleMode = RescaleMode::kNearest;
1147 }
1148
1149 // Within a rescaling pass A is the input (if not null) and B is the output. At the end of the
1150 // pass B is moved to A. If 'this' is the input on the first pass then tempA is null.
1151 std::unique_ptr<SurfaceFillContext> tempA;
1152 std::unique_ptr<SurfaceFillContext> tempB;
1153
1154 // Assume we should ignore the rescale linear request if the surface has no color space since
1155 // it's unclear how we'd linearize from an unknown color space.
1156 if (rescaleGamma == RescaleGamma::kLinear && this->colorInfo().colorSpace() &&
1157 !this->colorInfo().colorSpace()->gammaIsLinear()) {
1158 // Colorspace transformations are always handled by drawing so we need to be texturable
1159 std::tie(texView, srcRect) = ensureTexturable(texView, srcRect);
1160 if (!texView) {
1161 return false;
1162 }
1163 auto cs = this->colorInfo().colorSpace()->makeLinearGamma();
1164 // We'll fall back to kRGBA_8888 if half float not supported.
1166 dst->colorInfo().alphaType(),
1167 std::move(cs),
1168 srcRect.size());
1169 auto linearRTC = fContext->priv().makeSFCWithFallback(std::move(ii),
1171 /* sampleCount= */ 1,
1172 skgpu::Mipmapped::kNo,
1173 texView.proxy()->isProtected(),
1174 dst->origin());
1175 if (!linearRTC) {
1176 return false;
1177 }
1178 auto fp = GrTextureEffect::Make(std::move(texView),
1179 this->colorInfo().alphaType(),
1180 SkMatrix::Translate(srcRect.topLeft()),
1181 GrSamplerState::Filter::kNearest,
1182 GrSamplerState::MipmapMode::kNone);
1183 fp = GrColorSpaceXformEffect::Make(std::move(fp),
1184 this->colorInfo(),
1185 linearRTC->colorInfo());
1186 linearRTC->fillWithFP(std::move(fp));
1187 texView = linearRTC->readSurfaceView();
1188 SkASSERT(texView.asTextureProxy());
1189 tempA = std::move(linearRTC);
1190 srcRect = SkIRect::MakeSize(srcRect.size());
1191 }
1192
1193 do {
1194 SkISize nextDims = finalSize;
1195 if (rescaleMode != RescaleMode::kNearest && rescaleMode != RescaleMode::kLinear) {
1196 if (srcRect.width() > finalSize.width()) {
1197 nextDims.fWidth = std::max((srcRect.width() + 1)/2, finalSize.width());
1198 } else if (srcRect.width() < finalSize.width()) {
1199 nextDims.fWidth = std::min(srcRect.width()*2, finalSize.width());
1200 }
1201 if (srcRect.height() > finalSize.height()) {
1202 nextDims.fHeight = std::max((srcRect.height() + 1)/2, finalSize.height());
1203 } else if (srcRect.height() < finalSize.height()) {
1204 nextDims.fHeight = std::min(srcRect.height()*2, finalSize.height());
1205 }
1206 }
1207 auto input = tempA ? tempA.get() : this;
1209 SurfaceFillContext* stepDst;
1210 SkIRect stepDstRect;
1211 if (nextDims == finalSize) {
1212 stepDst = dst;
1213 stepDstRect = dstRect;
1214 xform = GrColorSpaceXform::Make(input->colorInfo(), dst->colorInfo());
1215 } else {
1216 GrImageInfo nextInfo(input->colorInfo(), nextDims);
1217
1219 /* sampleCount= */ 1,
1220 skgpu::Mipmapped::kNo,
1221 texView.proxy()->isProtected());
1222 if (!tempB) {
1223 return false;
1224 }
1225 stepDst = tempB.get();
1226 stepDstRect = SkIRect::MakeSize(tempB->dimensions());
1227 }
1228 std::unique_ptr<GrFragmentProcessor> fp;
1229 if (rescaleMode == RescaleMode::kRepeatedCubic) {
1230 // Cubic sampling is always handled by drawing with a shader, so we must be texturable
1231 std::tie(texView, srcRect) = ensureTexturable(texView, srcRect);
1232 if (!texView) {
1233 return false;
1234 }
1236 if (nextDims.width() == srcRect.width()) {
1238 } else if (nextDims.height() == srcRect.height()) {
1240 }
1241 static constexpr auto kWM = GrSamplerState::WrapMode::kClamp;
1242 static constexpr auto kKernel = GrBicubicEffect::gCatmullRom;
1243 fp = GrBicubicEffect::MakeSubset(std::move(texView),
1244 input->colorInfo().alphaType(),
1245 SkMatrix::I(),
1246 kWM,
1247 kWM,
1248 SkRect::Make(srcRect),
1249 kKernel,
1250 dir,
1251 *this->caps());
1252 } else {
1253 auto filter = rescaleMode == RescaleMode::kNearest ? GrSamplerState::Filter::kNearest
1254 : GrSamplerState::Filter::kLinear;
1255 if (xform ||
1256 texView.origin() != stepDst->origin() ||
1257 !stepDst->copyScaled(texView.refProxy(), srcRect, stepDstRect, filter)) {
1258 // We could not or were unable to successful perform a scaling blit (which can be
1259 // much faster if texView isn't already texturable). Scale by drawing instead.
1260 std::tie(texView, srcRect) = ensureTexturable(texView, srcRect);
1261 if (!texView) {
1262 return false;
1263 }
1264 auto srcRectF = SkRect::Make(srcRect);
1265 fp = GrTextureEffect::MakeSubset(std::move(texView),
1266 this->colorInfo().alphaType(),
1267 SkMatrix::I(),
1268 {filter, GrSamplerState::MipmapMode::kNone},
1269 srcRectF,
1270 srcRectF,
1271 *this->caps());
1272 }
1273 }
1274 if (xform) {
1275 SkASSERT(SkToBool(fp)); // shouldn't have done a copy if there was a color xform
1276 fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
1277 }
1278 if (fp) {
1279 // When fp is not null, we scale by drawing; if it is null, presumably the src has
1280 // already been copied into stepDst.
1281 stepDst->fillRectToRectWithFP(srcRect, stepDstRect, std::move(fp));
1282 }
1283 texView = stepDst->readSurfaceView();
1284 tempA = std::move(tempB);
1285 srcRect = SkIRect::MakeSize(nextDims);
1286 } while (srcRect.size() != finalSize);
1287 return true;
1288}
static constexpr SkCubicResampler gCatmullRom
static std::unique_ptr< GrFragmentProcessor > MakeSubset(GrSurfaceProxyView view, SkAlphaType, const SkMatrix &, const GrSamplerState::WrapMode wrapX, const GrSamplerState::WrapMode wrapY, const SkRect &subset, SkCubicResampler, Direction, const GrCaps &)
static std::unique_ptr< GrFragmentProcessor > Make(std::unique_ptr< GrFragmentProcessor > child, SkColorSpace *src, SkAlphaType srcAT, SkColorSpace *dst, SkAlphaType dstAT)
static sk_sp< GrColorSpaceXform > Make(SkColorSpace *src, SkAlphaType srcAT, SkColorSpace *dst, SkAlphaType dstAT)
GrProtected isProtected() const
static std::unique_ptr< GrFragmentProcessor > MakeSubset(GrSurfaceProxyView, SkAlphaType, const SkMatrix &, GrSamplerState, const SkRect &subset, const GrCaps &caps, const float border[4]=kDefaultBorder, bool alwaysUseShaderTileMode=false)
sk_sp< SkColorSpace > makeLinearGamma() const
static const SkMatrix & I()
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 Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition switches.h:145
constexpr int32_t height() const
Definition SkRect.h:165
constexpr int32_t width() const
Definition SkRect.h:158
constexpr SkIPoint topLeft() const
Definition SkRect.h:151
bool contains(int32_t x, int32_t y) const
Definition SkRect.h:463
int32_t fHeight
Definition SkSize.h:18
int32_t fWidth
Definition SkSize.h:17
static SkRect Make(const SkISize &size)
Definition SkRect.h:669

◆ transferPixels()

SurfaceContext::PixelTransferResult skgpu::ganesh::SurfaceContext::transferPixels ( GrColorType  colorType,
const SkIRect rect 
)
protected

Definition at line 1290 of file SurfaceContext.cpp.

1291 {
1292 SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
1293 SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
1294 auto direct = fContext->asDirectContext();
1295 if (!direct) {
1296 return {};
1297 }
1298 auto rtProxy = this->asRenderTargetProxy();
1299 if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
1300 return {};
1301 }
1302
1303 auto proxy = this->asSurfaceProxy();
1304 auto supportedRead = this->caps()->supportedReadPixelsColorType(this->colorInfo().colorType(),
1305 proxy->backendFormat(), dstCT);
1306 // Fail if read color type does not have all of dstCT's color channels and those missing color
1307 // channels are in the src.
1308 uint32_t dstChannels = GrColorTypeChannelFlags(dstCT);
1309 uint32_t legalReadChannels = GrColorTypeChannelFlags(supportedRead.fColorType);
1310 uint32_t srcChannels = GrColorTypeChannelFlags(this->colorInfo().colorType());
1311 if ((~legalReadChannels & dstChannels) & srcChannels) {
1312 return {};
1313 }
1314
1315 if (!this->caps()->transferFromSurfaceToBufferSupport() ||
1316 !supportedRead.fOffsetAlignmentForTransferBuffer) {
1317 return {};
1318 }
1319
1320 size_t rowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * rect.width();
1321 rowBytes = SkAlignTo(rowBytes, this->caps()->transferBufferRowBytesAlignment());
1322 size_t size = rowBytes * rect.height();
1323 // By using kStream_GrAccessPattern here, we are not able to cache and reuse the buffer for
1324 // multiple reads. Switching to kDynamic_GrAccessPattern would allow for this, however doing
1325 // so causes a crash in a chromium test. See skbug.com/11297
1326 auto buffer = direct->priv().resourceProvider()->createBuffer(
1327 size,
1331 if (!buffer) {
1332 return {};
1333 }
1334 auto srcRect = rect;
1335 bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
1336 if (flip) {
1337 srcRect = SkIRect::MakeLTRB(rect.fLeft, this->height() - rect.fBottom, rect.fRight,
1338 this->height() - rect.fTop);
1339 }
1341 this->colorInfo().colorType(),
1342 supportedRead.fColorType, buffer, 0);
1343 PixelTransferResult result;
1344 result.fTransferBuffer = std::move(buffer);
1345 auto at = this->colorInfo().alphaType();
1346 if (supportedRead.fColorType != dstCT || flip) {
1347 int w = rect.width(), h = rect.height();
1348 GrImageInfo srcInfo(supportedRead.fColorType, at, nullptr, w, h);
1349 GrImageInfo dstInfo(dstCT, at, nullptr, w, h);
1350 result.fRowBytes = dstInfo.minRowBytes();
1351 result.fPixelConverter = [dstInfo, srcInfo, rowBytes](
1352 void* dst, const void* src) {
1353 GrConvertPixels( GrPixmap(dstInfo, dst, dstInfo.minRowBytes()),
1354 GrCPixmap(srcInfo, src, rowBytes));
1355 };
1356 } else {
1357 result.fRowBytes = rowBytes;
1358 }
1359 return result;
1360}
static constexpr size_t GrColorTypeBytesPerPixel(GrColorType ct)
@ kStream_GrAccessPattern
static constexpr size_t SkAlignTo(size_t x, size_t alignment)
Definition SkAlign.h:33
virtual GrDirectContext * asDirectContext()
void newTransferFromRenderTask(const sk_sp< GrSurfaceProxy > &srcProxy, const SkIRect &srcRect, GrColorType surfaceColorType, GrColorType dstColorType, sk_sp< GrGpuBuffer > dstBuffer, size_t dstOffset)
GrDrawingManager * drawingManager()
static const uint8_t buffer[]
SkScalar w
SkScalar h
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91

◆ width()

int skgpu::ganesh::SurfaceContext::width ( ) const
inline

Definition at line 62 of file SurfaceContext.h.

62{ return fReadView.proxy()->width(); }
int width() const

◆ writePixels() [1/2]

bool skgpu::ganesh::SurfaceContext::writePixels ( GrDirectContext dContext,
const GrCPixmap  src[],
int  numLevels 
)

Fully populates either the base level or all MIP levels of the GrSurface with pixel data.

Parameters
dContextThe direct context to use
srcArray of pixmaps
numLevelsNumber of pixmaps in src. To succeed this must be 1 or the total number of MIP levels.

Definition at line 287 of file SurfaceContext.cpp.

289 {
292 SkDEBUGCODE(this->validate();)
293
294 SkASSERT(dContext);
295 SkASSERT(numLevels >= 1);
296 SkASSERT(src);
297
298 if (numLevels == 1) {
299 if (src->dimensions() != this->dimensions()) {
300 return false;
301 }
302 return this->writePixels(dContext, src[0], {0, 0});
303 }
304 if (!this->asTextureProxy() ||
305 this->asTextureProxy()->proxyMipmapped() == skgpu::Mipmapped::kNo) {
306 return false;
307 }
308
309 SkISize dims = this->dimensions();
310 if (numLevels != SkMipmap::ComputeLevelCount(dims) + 1) {
311 return false;
312 }
313 for (int i = 0; i < numLevels; ++i) {
314 if (src[i].colorInfo() != src[0].colorInfo()) {
315 return false;
316 }
317 if (dims != src[i].dimensions()) {
318 return false;
319 }
320 if (!src[i].info().bpp() || src[i].rowBytes() % src[i].info().bpp()) {
321 return false;
322 }
323 dims = {std::max(1, dims.width()/2), std::max(1, dims.height()/2)};
324 }
325 return this->internalWritePixels(dContext, src, numLevels, {0, 0});
326}
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition SkMipmap.cpp:134
bool writePixels(GrDirectContext *dContext, GrCPixmap src, SkIPoint dstPt)

◆ writePixels() [2/2]

bool skgpu::ganesh::SurfaceContext::writePixels ( GrDirectContext dContext,
GrCPixmap  src,
SkIPoint  dstPt 
)

Writes a rectangle of pixels from src into the surfaceDrawContext at the specified position.

Parameters
dContextThe direct context to use
srcsource for the write
dstPtoffset w/in the surface context at which to write

Definition at line 270 of file SurfaceContext.cpp.

272 {
275 SkDEBUGCODE(this->validate();)
276
277 src = src.clip(this->dimensions(), &dstPt);
278 if (!src.hasPixels()) {
279 return false;
280 }
281 if (!src.info().bpp() || src.rowBytes() % src.info().bpp()) {
282 return false;
283 }
284 return this->internalWritePixels(dContext, &src, 1, dstPt);
285}

Friends And Related Symbol Documentation

◆ ::GrRecordingContextPriv

friend class ::GrRecordingContextPriv
friend

Definition at line 213 of file SurfaceContext.h.

◆ ::GrSurfaceProxy

friend class ::GrSurfaceProxy
friend

Definition at line 214 of file SurfaceContext.h.

Member Data Documentation

◆ fContext

SkDEBUGCODE (void validate() const;) SkDEBUGCODE(skgpu GrRecordingContext* skgpu::ganesh::SurfaceContext::fContext
protected

Definition at line 185 of file SurfaceContext.h.

◆ fReadView

GrSurfaceProxyView skgpu::ganesh::SurfaceContext::fReadView
protected

Definition at line 187 of file SurfaceContext.h.


The documentation for this class was generated from the following files: