Flutter Engine
The Flutter Engine
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
GrSurfaceProxyView fReadView

◆ ~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 632 of file SurfaceContext.cpp.

636 {
638 PixelTransferResult>;
639
640 SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
641 SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
642
643 if (!dContext || this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
644 callback(callbackContext, nullptr);
645 return;
646 }
647
648 auto mappedBufferManager = dContext->priv().clientMappedBufferManager();
649
650 auto transferResult = this->transferPixels(SkColorTypeToGrColorType(colorType), rect);
651
652 if (!transferResult.fTransferBuffer) {
653 auto ii = SkImageInfo::Make(rect.size(), colorType, this->colorInfo().alphaType(),
654 this->colorInfo().refColorSpace());
656 auto result = std::make_unique<AsyncReadResult>(kInvalid);
658 result->addCpuPlane(pm.pixelStorage(), pm.rowBytes());
659
660 SkIPoint pt{rect.fLeft, rect.fTop};
661 if (!this->readPixels(dContext, pm, pt)) {
662 callback(callbackContext, nullptr);
663 return;
664 }
665 callback(callbackContext, std::move(result));
666 return;
667 }
668
669 struct FinishContext {
670 ReadPixelsCallback* fClientCallback;
671 ReadPixelsContext fClientContext;
672 SkISize fSize;
673 GrClientMappedBufferManager* fMappedBufferManager;
674 PixelTransferResult fTransferResult;
675 };
676 // Assumption is that the caller would like to flush. We could take a parameter or require an
677 // explicit flush from the caller. We'd have to have a way to defer attaching the finish
678 // callback to GrGpu until after the next flush that flushes our op list, though.
679 auto* finishContext = new FinishContext{callback,
680 callbackContext,
681 rect.size(),
682 mappedBufferManager,
683 std::move(transferResult)};
684 auto finishCallback = [](GrGpuFinishedContext c) {
685 const auto* context = reinterpret_cast<const FinishContext*>(c);
686 auto manager = context->fMappedBufferManager;
687 auto result = std::make_unique<AsyncReadResult>(manager->ownerID());
688 if (!result->addTransferResult(context->fTransferResult,
689 context->fSize,
690 context->fTransferResult.fRowBytes,
691 manager)) {
692 result.reset();
693 }
694 (*context->fClientCallback)(context->fClientContext, std::move(result));
695 delete context;
696 };
697 GrFlushInfo flushInfo;
698 flushInfo.fFinishedContext = finishContext;
699 flushInfo.fFinishedProc = finishCallback;
700
701 dContext->priv().flushSurface(
703}
static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct)
Definition: GrTypesPriv.h:629
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
Definition: SkSize.h:16
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 561 of file SurfaceContext.cpp.

567 {
568 if (!dContext) {
569 callback(callbackContext, nullptr);
570 return;
571 }
572 auto rt = this->asRenderTargetProxy();
573 if (rt && rt->wrapsVkSecondaryCB()) {
574 callback(callbackContext, nullptr);
575 return;
576 }
577 if (rt && rt->framebufferOnly()) {
578 callback(callbackContext, nullptr);
579 return;
580 }
581 auto dstCT = SkColorTypeToGrColorType(info.colorType());
582 if (dstCT == GrColorType::kUnknown) {
583 callback(callbackContext, nullptr);
584 return;
585 }
586 bool needsRescale = srcRect.size() != info.dimensions() ||
588 this->colorInfo().alphaType() != info.alphaType() ||
589 !SkColorSpace::Equals(this->colorInfo().colorSpace(), info.colorSpace());
590 auto surfaceBackendFormat = this->asSurfaceProxy()->backendFormat();
591 auto readInfo = this->caps()->supportedReadPixelsColorType(this->colorInfo().colorType(),
592 surfaceBackendFormat,
593 dstCT);
594 // Fail if we can't read from the source surface's color type.
595 if (readInfo.fColorType == GrColorType::kUnknown) {
596 callback(callbackContext, nullptr);
597 return;
598 }
599 // Fail if read color type does not have all of dstCT's color channels and those missing color
600 // channels are in the src.
601 uint32_t dstChannels = GrColorTypeChannelFlags(dstCT);
602 uint32_t legalReadChannels = GrColorTypeChannelFlags(readInfo.fColorType);
603 uint32_t srcChannels = GrColorTypeChannelFlags(this->colorInfo().colorType());
604 if ((~legalReadChannels & dstChannels) & srcChannels) {
605 callback(callbackContext, nullptr);
606 return;
607 }
608
609 std::unique_ptr<SurfaceFillContext> tempFC;
610 int x = srcRect.fLeft;
611 int y = srcRect.fTop;
612 if (needsRescale) {
613 auto tempInfo = GrImageInfo(info).makeColorType(this->colorInfo().colorType());
614 tempFC = this->rescale(tempInfo, kTopLeft_GrSurfaceOrigin, srcRect,
615 rescaleGamma, rescaleMode);
616 if (!tempFC) {
617 callback(callbackContext, nullptr);
618 return;
619 }
620 SkASSERT(SkColorSpace::Equals(tempFC->colorInfo().colorSpace(), info.colorSpace()));
621 SkASSERT(tempFC->origin() == kTopLeft_GrSurfaceOrigin);
622 x = y = 0;
623 }
624 auto srcCtx = tempFC ? tempFC.get() : this;
625 return srcCtx->asyncReadPixels(dContext,
626 SkIRect::MakePtSize({x, y}, info.dimensions()),
627 info.colorType(),
628 callback,
629 callbackContext);
630}
static constexpr uint32_t GrColorTypeChannelFlags(GrColorType ct)
Definition: GrTypesPriv.h:661
@ 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
SkAlphaType alphaType() const
Definition: GrColorInfo.h:44
GrImageInfo makeColorType(GrColorType ct) const
Definition: GrImageInfo.cpp:38
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
Definition: SkImageInfo.h:375

◆ 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 705 of file SurfaceContext.cpp.

714 {
716 PixelTransferResult>;
717
718 SkASSERT(srcRect.fLeft >= 0 && srcRect.fRight <= this->width());
719 SkASSERT(srcRect.fTop >= 0 && srcRect.fBottom <= this->height());
720 SkASSERT(!dstSize.isZero());
721 SkASSERT((dstSize.width() % 2 == 0) && (dstSize.height() % 2 == 0));
722
723 if (!dContext) {
724 callback(callbackContext, nullptr);
725 return;
726 }
727 auto rt = this->asRenderTargetProxy();
728 if (rt && rt->wrapsVkSecondaryCB()) {
729 callback(callbackContext, nullptr);
730 return;
731 }
732 if (rt && rt->framebufferOnly()) {
733 callback(callbackContext, nullptr);
734 return;
735 }
736 if (this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
737 callback(callbackContext, nullptr);
738 return;
739 }
740 int x = srcRect.fLeft;
741 int y = srcRect.fTop;
742 bool needsRescale = srcRect.size() != dstSize ||
743 !SkColorSpace::Equals(this->colorInfo().colorSpace(), dstColorSpace.get());
744 GrSurfaceProxyView srcView = this->readSurfaceView();
745 if (needsRescale) {
746 auto info = SkImageInfo::Make(dstSize,
748 this->colorInfo().alphaType(),
749 dstColorSpace);
750 // TODO: Incorporate the YUV conversion into last pass of rescaling.
751 auto tempFC = this->rescale(info,
753 srcRect,
754 rescaleGamma,
755 rescaleMode);
756 if (!tempFC) {
757 callback(callbackContext, nullptr);
758 return;
759 }
760 SkASSERT(SkColorSpace::Equals(tempFC->colorInfo().colorSpace(), info.colorSpace()));
761 SkASSERT(tempFC->origin() == kTopLeft_GrSurfaceOrigin);
762 x = y = 0;
763 srcView = tempFC->readSurfaceView();
764 } else if (!srcView.asTextureProxy()) {
765 srcView = GrSurfaceProxyView::Copy(
766 fContext,
767 std::move(srcView),
769 srcRect,
772 /*label=*/"SurfaceContext_AsyncRescaleAndReadPixelsYUV420");
773 if (!srcView) {
774 // If we can't get a texture copy of the contents then give up.
775 callback(callbackContext, nullptr);
776 return;
777 }
778 SkASSERT(srcView.asTextureProxy());
779 x = y = 0;
780 }
781
782 auto yaInfo = SkImageInfo::MakeA8(dstSize);
783 auto yFC = dContext->priv().makeSFCWithFallback(yaInfo, SkBackingFit::kApprox,
784 /* sampleCount= */ 1,
786 std::unique_ptr<SurfaceFillContext> aFC;
787 if (readAlpha) {
788 aFC = dContext->priv().makeSFCWithFallback(yaInfo, SkBackingFit::kApprox,
789 /* sampleCount= */ 1,
791 }
792
793 auto uvInfo = yaInfo.makeWH(yaInfo.width()/2, yaInfo.height()/2);
794 auto uFC = dContext->priv().makeSFCWithFallback(uvInfo, SkBackingFit::kApprox,
795 /* sampleCount= */ 1,
797 auto vFC = dContext->priv().makeSFCWithFallback(uvInfo, SkBackingFit::kApprox,
798 /* sampleCount= */ 1,
800
801 if (!yFC || !uFC || !vFC || (readAlpha && !aFC)) {
802 callback(callbackContext, nullptr);
803 return;
804 }
805
806 float baseM[20];
807 SkColorMatrix_RGB2YUV(yuvColorSpace, baseM);
808
809 // TODO: Use one transfer buffer for all three planes to reduce map/unmap cost?
810
811 auto texMatrix = SkMatrix::Translate(x, y);
812
813 auto [readCT, offsetAlignment] =
814 this->caps()->supportedReadPixelsColorType(yFC->colorInfo().colorType(),
815 yFC->asSurfaceProxy()->backendFormat(),
817 if (readCT == GrColorType::kUnknown) {
818 callback(callbackContext, nullptr);
819 return;
820 }
821 bool doSynchronousRead = !this->caps()->transferFromSurfaceToBufferSupport() ||
822 !offsetAlignment;
823 PixelTransferResult yTransfer, aTransfer, uTransfer, vTransfer;
824
825 // This matrix generates (r,g,b,a) = (0, 0, 0, y)
826 float yM[20];
827 std::fill_n(yM, 15, 0.f);
828 std::copy_n(baseM + 0, 5, yM + 15);
829
830 auto yFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix);
831 yFP = GrFragmentProcessor::ColorMatrix(std::move(yFP),
832 yM,
833 /*unpremulInput=*/false,
834 /*clampRGBOutput=*/true,
835 /*premulOutput=*/false);
836 yFC->fillWithFP(std::move(yFP));
837 if (!doSynchronousRead) {
838 yTransfer = yFC->transferPixels(GrColorType::kAlpha_8,
839 SkIRect::MakeSize(yFC->dimensions()));
840 if (!yTransfer.fTransferBuffer) {
841 callback(callbackContext, nullptr);
842 return;
843 }
844 }
845
846 if (readAlpha) {
847 auto aFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix);
848 SkASSERT(baseM[15] == 0 &&
849 baseM[16] == 0 &&
850 baseM[17] == 0 &&
851 baseM[18] == 1 &&
852 baseM[19] == 0);
853 aFC->fillWithFP(std::move(aFP));
854 if (!doSynchronousRead) {
855 aTransfer = aFC->transferPixels(GrColorType::kAlpha_8,
856 SkIRect::MakeSize(aFC->dimensions()));
857 if (!aTransfer.fTransferBuffer) {
858 callback(callbackContext, nullptr);
859 return;
860 }
861 }
862 }
863
864 texMatrix.preScale(2.f, 2.f);
865 // This matrix generates (r,g,b,a) = (0, 0, 0, u)
866 float uM[20];
867 std::fill_n(uM, 15, 0.f);
868 std::copy_n(baseM + 5, 5, uM + 15);
869
870 auto uFP = GrTextureEffect::Make(srcView,
871 this->colorInfo().alphaType(),
872 texMatrix,
874 uFP = GrFragmentProcessor::ColorMatrix(std::move(uFP),
875 uM,
876 /*unpremulInput=*/false,
877 /*clampRGBOutput=*/true,
878 /*premulOutput=*/false);
879 uFC->fillWithFP(std::move(uFP));
880 if (!doSynchronousRead) {
881 uTransfer = uFC->transferPixels(GrColorType::kAlpha_8,
882 SkIRect::MakeSize(uFC->dimensions()));
883 if (!uTransfer.fTransferBuffer) {
884 callback(callbackContext, nullptr);
885 return;
886 }
887 }
888
889 // This matrix generates (r,g,b,a) = (0, 0, 0, v)
890 float vM[20];
891 std::fill_n(vM, 15, 0.f);
892 std::copy_n(baseM + 10, 5, vM + 15);
893 auto vFP = GrTextureEffect::Make(std::move(srcView),
894 this->colorInfo().alphaType(),
895 texMatrix,
897 vFP = GrFragmentProcessor::ColorMatrix(std::move(vFP),
898 vM,
899 /*unpremulInput=*/false,
900 /*clampRGBOutput=*/true,
901 /*premulOutput=*/false);
902 vFC->fillWithFP(std::move(vFP));
903
904 if (!doSynchronousRead) {
905 vTransfer = vFC->transferPixels(GrColorType::kAlpha_8,
906 SkIRect::MakeSize(vFC->dimensions()));
907 if (!vTransfer.fTransferBuffer) {
908 callback(callbackContext, nullptr);
909 return;
910 }
911 }
912
913 if (doSynchronousRead) {
914 GrPixmap yPmp = GrPixmap::Allocate(yaInfo);
915 GrPixmap uPmp = GrPixmap::Allocate(uvInfo);
916 GrPixmap vPmp = GrPixmap::Allocate(uvInfo);
917 GrPixmap aPmp;
918 if (readAlpha) {
919 aPmp = GrPixmap::Allocate(yaInfo);
920 }
921 if (!yFC->readPixels(dContext, yPmp, {0, 0}) ||
922 !uFC->readPixels(dContext, uPmp, {0, 0}) ||
923 !vFC->readPixels(dContext, vPmp, {0, 0}) ||
924 (readAlpha && !aFC->readPixels(dContext, aPmp, {0, 0}))) {
925 callback(callbackContext, nullptr);
926 return;
927 }
928 auto result = std::make_unique<AsyncReadResult>(dContext->directContextID());
929 result->addCpuPlane(yPmp.pixelStorage(), yPmp.rowBytes());
930 result->addCpuPlane(uPmp.pixelStorage(), uPmp.rowBytes());
931 result->addCpuPlane(vPmp.pixelStorage(), vPmp.rowBytes());
932 if (readAlpha) {
933 result->addCpuPlane(aPmp.pixelStorage(), aPmp.rowBytes());
934 }
935 callback(callbackContext, std::move(result));
936 return;
937 }
938
939 struct FinishContext {
940 ReadPixelsCallback* fClientCallback;
941 ReadPixelsContext fClientContext;
942 GrClientMappedBufferManager* fMappedBufferManager;
943 SkISize fSize;
944 PixelTransferResult fYTransfer;
945 PixelTransferResult fUTransfer;
946 PixelTransferResult fVTransfer;
947 PixelTransferResult fATransfer;
948 };
949 // Assumption is that the caller would like to flush. We could take a parameter or require an
950 // explicit flush from the caller. We'd have to have a way to defer attaching the finish
951 // callback to GrGpu until after the next flush that flushes our op list, though.
952 auto* finishContext = new FinishContext{callback,
953 callbackContext,
954 dContext->priv().clientMappedBufferManager(),
955 dstSize,
956 std::move(yTransfer),
957 std::move(uTransfer),
958 std::move(vTransfer),
959 std::move(aTransfer)};
960 auto finishCallback = [](GrGpuFinishedContext c) {
961 const auto* context = reinterpret_cast<const FinishContext*>(c);
962 auto manager = context->fMappedBufferManager;
963 auto result = std::make_unique<AsyncReadResult>(manager->ownerID());
964 if (!result->addTransferResult(context->fYTransfer,
965 context->fSize,
966 context->fYTransfer.fRowBytes,
967 manager)) {
968 (*context->fClientCallback)(context->fClientContext, nullptr);
969 delete context;
970 return;
971 }
972 SkISize uvSize = {context->fSize.width() / 2, context->fSize.height() / 2};
973 if (!result->addTransferResult(context->fUTransfer,
974 uvSize,
975 context->fUTransfer.fRowBytes,
976 manager)) {
977 (*context->fClientCallback)(context->fClientContext, nullptr);
978 delete context;
979 return;
980 }
981 if (!result->addTransferResult(context->fVTransfer,
982 uvSize,
983 context->fVTransfer.fRowBytes,
984 manager)) {
985 (*context->fClientCallback)(context->fClientContext, nullptr);
986 delete context;
987 return;
988 }
989 if (context->fATransfer.fTransferBuffer &&
990 !result->addTransferResult(context->fATransfer,
991 context->fSize,
992 context->fATransfer.fRowBytes,
993 manager)) {
994 (*context->fClientCallback)(context->fClientContext, nullptr);
995 delete context;
996 return;
997 }
998 (*context->fClientCallback)(context->fClientContext, std::move(result));
999 delete context;
1000 };
1001 GrFlushInfo flushInfo;
1002 flushInfo.fFinishedContext = finishContext;
1003 flushInfo.fFinishedProc = finishCallback;
1004 dContext->priv().flushSurface(
1006}
@ 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])
Definition: SkYUVMath.cpp:389
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()).
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()) {
149 if (canvas2DFastPath || srcIsCompressed) {
151 } else {
152 GrBackendFormat backendFormat =
154 if (!backendFormat.isValid()) {
156 }
157 }
158
159 SkAlphaType alphaType = canvas2DFastPath ? dst.alphaType()
160 : this->colorInfo().alphaType();
161 GrImageInfo tempInfo(colorType,
162 alphaType,
163 this->colorInfo().refColorSpace(),
164 dst.dimensions());
165 auto sfc = dContext->priv().makeSFC(
166 tempInfo, "SurfaceContext_ReadPixels", SkBackingFit::kApprox);
167 if (!sfc) {
168 return false;
169 }
170
171 std::unique_ptr<GrFragmentProcessor> fp;
172 if (canvas2DFastPath) {
174 this->readSurfaceView(), this->colorInfo().alphaType()));
175 if (dst.colorType() == GrColorType::kBGRA_8888) {
177 dst = GrPixmap(dst.info().makeColorType(GrColorType::kRGBA_8888),
178 dst.addr(),
179 dst.rowBytes());
180 }
181 } else {
182 fp = GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType());
183 }
184 if (!fp) {
185 return false;
186 }
187 sfc->fillRectToRectWithFP(SkIRect::MakePtSize(pt, dst.dimensions()),
188 SkIRect::MakeSize(dst.dimensions()),
189 std::move(fp));
190 pt = {0, 0};
191 tempCtx = std::move(sfc);
192 } else {
193 auto restrictions = this->caps()->getDstCopyRestrictions(this->asRenderTargetProxy(),
194 this->colorInfo().colorType());
196 static constexpr auto kFit = SkBackingFit::kExact;
197 static constexpr auto kBudgeted = skgpu::Budgeted::kYes;
198 static constexpr auto kMipMapped = skgpu::Mipmapped::kNo;
199 if (restrictions.fMustCopyWholeSrc) {
201 std::move(srcProxy),
202 this->origin(),
203 kMipMapped,
204 kFit,
205 kBudgeted,
206 /*label=*/"SurfaceContext_ReadPixelsWithCopyWholeSrc");
207 } else {
208 auto srcRect = SkIRect::MakePtSize(pt, dst.dimensions());
210 std::move(srcProxy),
211 this->origin(),
212 kMipMapped,
213 srcRect,
214 kFit,
215 kBudgeted,
216 /*label=*/"SurfaceContext_ReadPixels",
217 restrictions.fRectsMustMatch);
218 pt = {0, 0};
219 }
220 if (!copy) {
221 return false;
222 }
223 GrSurfaceProxyView view{std::move(copy), this->origin(), this->readSwizzle()};
224 tempCtx = dContext->priv().makeSC(std::move(view), this->colorInfo());
225 SkASSERT(tempCtx);
226 }
227 return tempCtx->readPixels(dContext, dst, pt);
228 }
229
230 bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
231
232 auto supportedRead = caps->supportedReadPixelsColorType(
233 this->colorInfo().colorType(), srcProxy->backendFormat(), dst.colorType());
234
235 bool makeTight =
236 !caps->readPixelsRowBytesSupport() && dst.rowBytes() != dst.info().minRowBytes();
237
238 bool convert = unpremul || premul || needColorConversion || flip || makeTight ||
239 (dst.colorType() != supportedRead.fColorType);
240
241 std::unique_ptr<char[]> tmpPixels;
242 GrPixmap tmp;
243 void* readDst = dst.addr();
244 size_t readRB = dst.rowBytes();
245 if (convert) {
246 GrImageInfo tmpInfo(supportedRead.fColorType,
247 this->colorInfo().alphaType(),
248 this->colorInfo().refColorSpace(),
249 dst.dimensions());
250 size_t tmpRB = tmpInfo.minRowBytes();
251 size_t size = tmpRB * tmpInfo.height();
252 // Chrome MSAN bots require the data to be initialized (hence the ()).
253 tmpPixels = std::make_unique<char[]>(size);
254 tmp = {tmpInfo, tmpPixels.get(), tmpRB};
255
256 readDst = tmpPixels.get();
257 readRB = tmpRB;
258 pt.fY = flip ? srcSurface->height() - pt.fY - dst.height() : pt.fY;
259 }
260
261 dContext->priv().flushSurface(srcProxy.get());
262 dContext->submit();
263 if (!dContext->priv().getGpu()->readPixels(srcSurface,
264 SkIRect::MakePtSize(pt, dst.dimensions()),
265 this->colorInfo().colorType(),
266 supportedRead.fColorType,
267 readDst,
268 readRB)) {
269 return false;
270 }
271
272 if (tmp.hasPixels()) {
273 return GrConvertPixels(dst, tmp, flip);
274 }
275 return true;
276}
bool GrConvertPixels(const GrPixmap &dst, const GrCPixmap &src, bool flipY)
#define GR_CREATE_TRACE_MARKER_CONTEXT(classname, op, context)
Definition: GrTracing.h:18
GrColorType
Definition: GrTypesPriv.h:540
SkAlphaType
Definition: SkAlphaType.h:26
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
#define RETURN_FALSE_IF_ABANDONED
#define ASSERT_SINGLE_OWNER
static uint32_t premul(uint32_t color)
bool isValid() const
bool matches(GrContext_Base *candidate) const
Definition: GrCaps.h:57
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)
virtual bool instantiate(GrResourceProvider *)=0
bool framebufferOnly() const
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 GrTextureProxy * asTextureProxy()
GrSurface * peekSurface() const
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
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 1089 of file SurfaceContext.cpp.

1093 {
1094 auto sfc = fContext->priv().makeSFCWithFallback(info,
1096 /* sampleCount= */ 1,
1098 this->asSurfaceProxy()->isProtected(),
1099 origin);
1100 if (!sfc || !this->rescaleInto(sfc.get(),
1101 SkIRect::MakeSize(sfc->dimensions()),
1102 srcRect,
1103 rescaleGamma,
1104 rescaleMode)) {
1105 return nullptr;
1106 }
1107 return sfc;
1108}
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 1110 of file SurfaceContext.cpp.

1114 {
1115 SkASSERT(dst);
1116 if (!SkIRect::MakeSize(dst->dimensions()).contains((dstRect))) {
1117 return false;
1118 }
1119
1120 auto rtProxy = this->asRenderTargetProxy();
1121 if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
1122 return false;
1123 }
1124
1125 if (this->asSurfaceProxy()->framebufferOnly()) {
1126 return false;
1127 }
1128
1129 GrSurfaceProxyView texView = this->readSurfaceView();
1130 // If we perform scaling as draws, texView must be texturable; if it's not already, we have to
1131 // make a copy. However, if the scaling can use copyScaled(), we can avoid this copy.
1132 auto ensureTexturable = [this](GrSurfaceProxyView texView, SkIRect srcRect) {
1133 if (!texView.asTextureProxy()) {
1134 // TODO: If copying supported specifying a renderable copy then we could return the copy
1135 // when there are no other conversions.
1137 std::move(texView),
1139 srcRect,
1142 "SurfaceContext_RescaleInto");
1143 if (texView) {
1144 SkASSERT(texView.asTextureProxy());
1145 srcRect = SkIRect::MakeSize(srcRect.size());
1146 }
1147 }
1148 return std::make_pair(std::move(texView), srcRect);
1149 };
1150
1151 SkISize finalSize = dstRect.size();
1152 if (finalSize == srcRect.size()) {
1153 rescaleGamma = RescaleGamma::kSrc;
1154 rescaleMode = RescaleMode::kNearest;
1155 }
1156
1157 // Within a rescaling pass A is the input (if not null) and B is the output. At the end of the
1158 // pass B is moved to A. If 'this' is the input on the first pass then tempA is null.
1159 std::unique_ptr<SurfaceFillContext> tempA;
1160 std::unique_ptr<SurfaceFillContext> tempB;
1161
1162 // Assume we should ignore the rescale linear request if the surface has no color space since
1163 // it's unclear how we'd linearize from an unknown color space.
1164 if (rescaleGamma == RescaleGamma::kLinear && this->colorInfo().colorSpace() &&
1165 !this->colorInfo().colorSpace()->gammaIsLinear()) {
1166 // Colorspace transformations are always handled by drawing so we need to be texturable
1167 std::tie(texView, srcRect) = ensureTexturable(texView, srcRect);
1168 if (!texView) {
1169 return false;
1170 }
1171 auto cs = this->colorInfo().colorSpace()->makeLinearGamma();
1172 // We'll fall back to kRGBA_8888 if half float not supported.
1174 dst->colorInfo().alphaType(),
1175 std::move(cs),
1176 srcRect.size());
1177 auto linearRTC = fContext->priv().makeSFCWithFallback(std::move(ii),
1179 /* sampleCount= */ 1,
1181 texView.proxy()->isProtected(),
1182 dst->origin());
1183 if (!linearRTC) {
1184 return false;
1185 }
1186 auto fp = GrTextureEffect::Make(std::move(texView),
1187 this->colorInfo().alphaType(),
1188 SkMatrix::Translate(srcRect.topLeft()),
1191 fp = GrColorSpaceXformEffect::Make(std::move(fp),
1192 this->colorInfo(),
1193 linearRTC->colorInfo());
1194 linearRTC->fillWithFP(std::move(fp));
1195 texView = linearRTC->readSurfaceView();
1196 SkASSERT(texView.asTextureProxy());
1197 tempA = std::move(linearRTC);
1198 srcRect = SkIRect::MakeSize(srcRect.size());
1199 }
1200
1201 do {
1202 SkISize nextDims = finalSize;
1203 if (rescaleMode != RescaleMode::kNearest && rescaleMode != RescaleMode::kLinear) {
1204 if (srcRect.width() > finalSize.width()) {
1205 nextDims.fWidth = std::max((srcRect.width() + 1)/2, finalSize.width());
1206 } else if (srcRect.width() < finalSize.width()) {
1207 nextDims.fWidth = std::min(srcRect.width()*2, finalSize.width());
1208 }
1209 if (srcRect.height() > finalSize.height()) {
1210 nextDims.fHeight = std::max((srcRect.height() + 1)/2, finalSize.height());
1211 } else if (srcRect.height() < finalSize.height()) {
1212 nextDims.fHeight = std::min(srcRect.height()*2, finalSize.height());
1213 }
1214 }
1215 auto input = tempA ? tempA.get() : this;
1217 SurfaceFillContext* stepDst;
1218 SkIRect stepDstRect;
1219 if (nextDims == finalSize) {
1220 stepDst = dst;
1221 stepDstRect = dstRect;
1222 xform = GrColorSpaceXform::Make(input->colorInfo(), dst->colorInfo());
1223 } else {
1224 GrImageInfo nextInfo(input->colorInfo(), nextDims);
1225
1227 /* sampleCount= */ 1,
1229 texView.proxy()->isProtected());
1230 if (!tempB) {
1231 return false;
1232 }
1233 stepDst = tempB.get();
1234 stepDstRect = SkIRect::MakeSize(tempB->dimensions());
1235 }
1236 std::unique_ptr<GrFragmentProcessor> fp;
1237 if (rescaleMode == RescaleMode::kRepeatedCubic) {
1238 // Cubic sampling is always handled by drawing with a shader, so we must be texturable
1239 std::tie(texView, srcRect) = ensureTexturable(texView, srcRect);
1240 if (!texView) {
1241 return false;
1242 }
1244 if (nextDims.width() == srcRect.width()) {
1246 } else if (nextDims.height() == srcRect.height()) {
1248 }
1249 static constexpr auto kWM = GrSamplerState::WrapMode::kClamp;
1250 static constexpr auto kKernel = GrBicubicEffect::gCatmullRom;
1251 fp = GrBicubicEffect::MakeSubset(std::move(texView),
1252 input->colorInfo().alphaType(),
1253 SkMatrix::I(),
1254 kWM,
1255 kWM,
1256 SkRect::Make(srcRect),
1257 kKernel,
1258 dir,
1259 *this->caps());
1260 } else {
1261 auto filter = rescaleMode == RescaleMode::kNearest ? GrSamplerState::Filter::kNearest
1263 if (xform ||
1264 texView.origin() != stepDst->origin() ||
1265 !stepDst->copyScaled(texView.refProxy(), srcRect, stepDstRect, filter)) {
1266 // We could not or were unable to successful perform a scaling blit (which can be
1267 // much faster if texView isn't already texturable). Scale by drawing instead.
1268 std::tie(texView, srcRect) = ensureTexturable(texView, srcRect);
1269 if (!texView) {
1270 return false;
1271 }
1272 auto srcRectF = SkRect::Make(srcRect);
1273 fp = GrTextureEffect::MakeSubset(std::move(texView),
1274 this->colorInfo().alphaType(),
1275 SkMatrix::I(),
1277 srcRectF,
1278 srcRectF,
1279 *this->caps());
1280 }
1281 }
1282 if (xform) {
1283 SkASSERT(SkToBool(fp)); // shouldn't have done a copy if there was a color xform
1284 fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
1285 }
1286 if (fp) {
1287 // When fp is not null, we scale by drawing; if it is null, presumably the src has
1288 // already been copied into stepDst.
1289 stepDst->fillRectToRectWithFP(srcRect, stepDstRect, std::move(fp));
1290 }
1291 texView = stepDst->readSurfaceView();
1292 tempA = std::move(tempB);
1293 srcRect = SkIRect::MakeSize(nextDims);
1294 } while (srcRect.size() != finalSize);
1295 return true;
1296}
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 &)
SkColorSpace * colorSpace() const
Definition: GrColorInfo.cpp:48
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()
Definition: SkMatrix.cpp:1544
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
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
Definition: SkRect.h:32
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 1298 of file SurfaceContext.cpp.

1299 {
1300 SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
1301 SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
1302 auto direct = fContext->asDirectContext();
1303 if (!direct) {
1304 return {};
1305 }
1306 auto rtProxy = this->asRenderTargetProxy();
1307 if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
1308 return {};
1309 }
1310
1311 auto proxy = this->asSurfaceProxy();
1312 auto supportedRead = this->caps()->supportedReadPixelsColorType(this->colorInfo().colorType(),
1313 proxy->backendFormat(), dstCT);
1314 // Fail if read color type does not have all of dstCT's color channels and those missing color
1315 // channels are in the src.
1316 uint32_t dstChannels = GrColorTypeChannelFlags(dstCT);
1317 uint32_t legalReadChannels = GrColorTypeChannelFlags(supportedRead.fColorType);
1318 uint32_t srcChannels = GrColorTypeChannelFlags(this->colorInfo().colorType());
1319 if ((~legalReadChannels & dstChannels) & srcChannels) {
1320 return {};
1321 }
1322
1323 if (!this->caps()->transferFromSurfaceToBufferSupport() ||
1324 !supportedRead.fOffsetAlignmentForTransferBuffer) {
1325 return {};
1326 }
1327
1328 size_t rowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * rect.width();
1329 rowBytes = SkAlignTo(rowBytes, this->caps()->transferBufferRowBytesAlignment());
1330 size_t size = rowBytes * rect.height();
1331 // By using kStream_GrAccessPattern here, we are not able to cache and reuse the buffer for
1332 // multiple reads. Switching to kDynamic_GrAccessPattern would allow for this, however doing
1333 // so causes a crash in a chromium test. See skbug.com/11297
1334 auto buffer = direct->priv().resourceProvider()->createBuffer(
1335 size,
1339 if (!buffer) {
1340 return {};
1341 }
1342 auto srcRect = rect;
1343 bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
1344 if (flip) {
1345 srcRect = SkIRect::MakeLTRB(rect.fLeft, this->height() - rect.fBottom, rect.fRight,
1346 this->height() - rect.fTop);
1347 }
1349 this->colorInfo().colorType(),
1350 supportedRead.fColorType, buffer, 0);
1351 PixelTransferResult result;
1352 result.fTransferBuffer = std::move(buffer);
1353 auto at = this->colorInfo().alphaType();
1354 if (supportedRead.fColorType != dstCT || flip) {
1355 int w = rect.width(), h = rect.height();
1356 GrImageInfo srcInfo(supportedRead.fColorType, at, nullptr, w, h);
1357 GrImageInfo dstInfo(dstCT, at, nullptr, w, h);
1358 result.fRowBytes = dstInfo.minRowBytes();
1359 result.fPixelConverter = [dstInfo, srcInfo, rowBytes](
1360 void* dst, const void* src) {
1361 GrConvertPixels( GrPixmap(dstInfo, dst, dstInfo.minRowBytes()),
1362 GrCPixmap(srcInfo, src, rowBytes));
1363 };
1364 } else {
1365 result.fRowBytes = rowBytes;
1366 }
1367 return result;
1368}
static constexpr size_t GrColorTypeBytesPerPixel(GrColorType ct)
Definition: GrTypesPriv.h:896
@ kStream_GrAccessPattern
Definition: GrTypesPriv.h:430
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()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
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 295 of file SurfaceContext.cpp.

297 {
300 SkDEBUGCODE(this->validate();)
301
302 SkASSERT(dContext);
303 SkASSERT(numLevels >= 1);
304 SkASSERT(src);
305
306 if (numLevels == 1) {
307 if (src->dimensions() != this->dimensions()) {
308 return false;
309 }
310 return this->writePixels(dContext, src[0], {0, 0});
311 }
312 if (!this->asTextureProxy() ||
313 this->asTextureProxy()->proxyMipmapped() == skgpu::Mipmapped::kNo) {
314 return false;
315 }
316
317 SkISize dims = this->dimensions();
318 if (numLevels != SkMipmap::ComputeLevelCount(dims) + 1) {
319 return false;
320 }
321 for (int i = 0; i < numLevels; ++i) {
322 if (src[i].colorInfo() != src[0].colorInfo()) {
323 return false;
324 }
325 if (dims != src[i].dimensions()) {
326 return false;
327 }
328 if (!src[i].info().bpp() || src[i].rowBytes() % src[i].info().bpp()) {
329 return false;
330 }
331 dims = {std::max(1, dims.width()/2), std::max(1, dims.height()/2)};
332 }
333 return this->internalWritePixels(dContext, src, numLevels, {0, 0});
334}
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 278 of file SurfaceContext.cpp.

280 {
283 SkDEBUGCODE(this->validate();)
284
285 src = src.clip(this->dimensions(), &dstPt);
286 if (!src.hasPixels()) {
287 return false;
288 }
289 if (!src.info().bpp() || src.rowBytes() % src.info().bpp()) {
290 return false;
291 }
292 return this->internalWritePixels(dContext, &src, 1, dstPt);
293}

Friends And Related Function 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: