From 2c86249465c28a532c8be55b6ba497021e3110ec Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Wed, 18 Jan 2017 10:08:39 -0500 Subject: [PATCH] Move read/write-Pixels up to GrSurfaceContext This still needs to be propagated out in several ways: replace more instances of GrSurface::read/write-Pixels add colorSpace to more instances of the TextureContext but it establishes a beach-head and is exciting enough as is. Change-Id: If86035aa0245e70b54541e83722b3c75bc5ade13 Reviewed-on: https://skia-review.googlesource.com/7172 Reviewed-by: Brian Osman Reviewed-by: Brian Salomon Commit-Queue: Robert Phillips --- include/gpu/GrRenderTargetContext.h | 38 ++-------- include/gpu/GrSurfaceContext.h | 44 +++++++++++- include/gpu/GrTextureContext.h | 8 ++- src/gpu/GrContext.cpp | 12 ++-- src/gpu/GrContextPriv.h | 3 +- src/gpu/GrDrawingManager.cpp | 21 ++++-- src/gpu/GrDrawingManager.h | 2 +- src/gpu/GrRenderTargetContext.cpp | 103 ++++++++++++++-------------- src/gpu/GrSurfaceContext.cpp | 2 + src/gpu/GrTextureContext.cpp | 60 ++++++++++++++-- src/gpu/text/GrAtlasGlyphCache.cpp | 3 +- src/image/SkImage_Gpu.cpp | 4 ++ src/image/SkImage_Gpu.h | 4 ++ tests/CopySurfaceTest.cpp | 2 +- tests/SurfaceTest.cpp | 30 +++++--- 15 files changed, 218 insertions(+), 118 deletions(-) diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h index 3636d5cfc1..e595a4f90f 100644 --- a/include/gpu/GrRenderTargetContext.h +++ b/include/gpu/GrRenderTargetContext.h @@ -316,34 +316,6 @@ public: */ void prepareForExternalIO(); - /** - * Reads a rectangle of pixels from the render target context. - * @param dstInfo image info for the destination - * @param dstBuffer destination pixels for the read - * @param dstRowBytes bytes in a row of 'dstBuffer' - * @param x x offset w/in the render target context from which to read - * @param y y offset w/in the render target context from which to read - * - * @return true if the read succeeded, false if not. The read can fail because of an - * unsupported pixel config. - */ - bool readPixels(const SkImageInfo& dstInfo, void* dstBuffer, size_t dstRowBytes, int x, int y); - - /** - * Writes a rectangle of pixels [srcInfo, srcBuffer, srcRowbytes] into the - * renderTargetContext at the specified position. - * @param srcInfo image info for the source pixels - * @param srcBuffer source for the write - * @param srcRowBytes bytes in a row of 'srcBuffer' - * @param x x offset w/in the render target context at which to write - * @param y y offset w/in the render target context at which to write - * - * @return true if the write succeeded, false if not. The write can fail because of an - * unsupported pixel config. - */ - bool writePixels(const SkImageInfo& srcInfo, const void* srcBuffer, size_t srcRowBytes, - int x, int y); - bool isStencilBufferMultisampled() const { return fRenderTargetProxy->isStencilBufferMultisampled(); } @@ -356,10 +328,7 @@ public: int height() const { return fRenderTargetProxy->height(); } GrPixelConfig config() const { return fRenderTargetProxy->config(); } int numColorSamples() const { return fRenderTargetProxy->numColorSamples(); } - bool isGammaCorrect() const { return SkToBool(fColorSpace.get()); } const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; } - SkColorSpace* getColorSpace() const { return fColorSpace.get(); } - sk_sp refColorSpace() const { return fColorSpace; } GrColorSpaceXform* getColorXformFromSRGB() const { return fColorXformFromSRGB.get(); } GrSurfaceOrigin origin() const { return fRenderTargetProxy->origin(); } @@ -396,7 +365,7 @@ public: protected: GrRenderTargetContext(GrContext*, GrDrawingManager*, sk_sp, - sk_sp, const SkSurfaceProps* surfaceProps, GrAuditTrail*, + sk_sp, const SkSurfaceProps*, GrAuditTrail*, GrSingleOwner*); GrDrawingManager* drawingManager() { return fDrawingManager; } @@ -469,6 +438,10 @@ private: const GrClip&, GrPaint&&, GrAA, const SkMatrix&, const SkPath&, const GrStyle&); bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override; + bool onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer, + size_t dstRowBytes, int x, int y) override; + bool onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer, + size_t srcRowBytes, int x, int y) override; // This entry point allows the GrTextContext-derived classes to add their ops to the GrOpList. void addDrawOp(const GrPipelineBuilder&, const GrClip&, std::unique_ptr); @@ -483,7 +456,6 @@ private: GrRenderTargetOpList* fOpList; GrInstancedPipelineInfo fInstancedPipelineInfo; - sk_sp fColorSpace; sk_sp fColorXformFromSRGB; SkSurfaceProps fSurfaceProps; diff --git a/include/gpu/GrSurfaceContext.h b/include/gpu/GrSurfaceContext.h index a772d19c27..6a40f2f8b2 100644 --- a/include/gpu/GrSurfaceContext.h +++ b/include/gpu/GrSurfaceContext.h @@ -30,6 +30,10 @@ class SK_API GrSurfaceContext : public SkRefCnt { public: ~GrSurfaceContext() override {} + SkColorSpace* getColorSpace() const { return fColorSpace.get(); } + sk_sp refColorSpace() const { return fColorSpace; } + bool isGammaCorrect() const { return SkToBool(fColorSpace.get()); } + /* * Copy 'src' into the proxy backing this context * @param src src of pixels @@ -52,6 +56,39 @@ public: SkIPoint::Make(0, 0)); } + /** + * Reads a rectangle of pixels from the render target context. + * @param dstInfo image info for the destination + * @param dstBuffer destination pixels for the read + * @param dstRowBytes bytes in a row of 'dstBuffer' + * @param x x offset w/in the render target context from which to read + * @param y y offset w/in the render target context from which to read + * + * @return true if the read succeeded, false if not. The read can fail because of an + * unsupported pixel config. + */ + bool readPixels(const SkImageInfo& dstInfo, void* dstBuffer, size_t dstRowBytes, + int x, int y) { + return this->onReadPixels(dstInfo, dstBuffer, dstRowBytes, x, y); + } + + /** + * Writes a rectangle of pixels [srcInfo, srcBuffer, srcRowbytes] into the + * renderTargetContext at the specified position. + * @param srcInfo image info for the source pixels + * @param srcBuffer source for the write + * @param srcRowBytes bytes in a row of 'srcBuffer' + * @param x x offset w/in the render target context at which to write + * @param y y offset w/in the render target context at which to write + * + * @return true if the write succeeded, false if not. The write can fail because of an + * unsupported pixel config. + */ + bool writePixels(const SkImageInfo& srcInfo, const void* srcBuffer, size_t srcRowBytes, + int x, int y) { + return this->onWritePixels(srcInfo, srcBuffer, srcRowBytes, x, y); + } + // TODO: this is virtual b.c. this object doesn't have a pointer to the wrapped GrSurfaceProxy? virtual GrSurfaceProxy* asDeferredSurface() = 0; virtual GrTextureProxy* asDeferredTexture() = 0; @@ -66,11 +103,12 @@ public: protected: friend class GrSurfaceContextPriv; - GrSurfaceContext(GrContext*, GrAuditTrail*, GrSingleOwner*); + GrSurfaceContext(GrContext*, sk_sp, GrAuditTrail*, GrSingleOwner*); SkDEBUGCODE(GrSingleOwner* singleOwner() { return fSingleOwner; }) GrContext* fContext; + sk_sp fColorSpace; GrAuditTrail* fAuditTrail; // In debug builds we guard against improper thread handling @@ -80,6 +118,10 @@ private: virtual bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0; + virtual bool onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer, + size_t dstRowBytes, int x, int y) = 0; + virtual bool onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer, + size_t srcRowBytes, int x, int y) = 0; typedef SkRefCnt INHERITED; }; diff --git a/include/gpu/GrTextureContext.h b/include/gpu/GrTextureContext.h index ef9613f3c3..b49b27255a 100644 --- a/include/gpu/GrTextureContext.h +++ b/include/gpu/GrTextureContext.h @@ -32,8 +32,8 @@ public: GrRenderTargetProxy* asDeferredRenderTarget() override; protected: - GrTextureContext(GrContext*, GrDrawingManager*, sk_sp, GrAuditTrail*, - GrSingleOwner*); + GrTextureContext(GrContext*, GrDrawingManager*, sk_sp, + sk_sp, GrAuditTrail*, GrSingleOwner*); GrDrawingManager* drawingManager() { return fDrawingManager; } @@ -43,6 +43,10 @@ private: friend class GrDrawingManager; // for ctor bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override; + bool onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer, + size_t dstRowBytes, int x, int y) override; + bool onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer, + size_t srcRowBytes, int x, int y) override; GrTextureOpList* getOpList(); diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 12560584ba..5543dff09a 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -593,14 +593,16 @@ sk_sp GrContextPriv::makeWrappedRenderTargetContext( surfaceProps); } -sk_sp GrContextPriv::makeWrappedSurfaceContext(sk_sp proxy) { +sk_sp GrContextPriv::makeWrappedSurfaceContext(sk_sp proxy, + sk_sp colorSpace) { ASSERT_SINGLE_OWNER_PRIV if (proxy->asRenderTargetProxy()) { - return this->drawingManager()->makeRenderTargetContext(std::move(proxy), nullptr, nullptr); + return this->drawingManager()->makeRenderTargetContext(std::move(proxy), + std::move(colorSpace), nullptr); } else { SkASSERT(proxy->asTextureProxy()); - return this->drawingManager()->makeTextureContext(std::move(proxy)); + return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace)); } } @@ -609,7 +611,7 @@ sk_sp GrContextPriv::makeWrappedSurfaceContext(sk_sp proxy(GrSurfaceProxy::MakeWrapped(std::move(surface))); - return this->makeWrappedSurfaceContext(std::move(proxy)); + return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); } sk_sp GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc, @@ -619,7 +621,7 @@ sk_sp GrContextPriv::makeDeferredSurfaceContext(const GrSurfac sk_sp proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc, fit, isDstBudgeted); - return this->makeWrappedSurfaceContext(std::move(proxy)); + return this->makeWrappedSurfaceContext(std::move(proxy), nullptr); } sk_sp GrContextPriv::makeBackendTextureRenderTargetContext( diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h index e24a588d1d..3315c94e91 100644 --- a/src/gpu/GrContextPriv.h +++ b/src/gpu/GrContextPriv.h @@ -28,7 +28,8 @@ public: // Create a surfaceContext that wraps an existing texture or renderTarget sk_sp makeWrappedSurfaceContext(sk_sp tex); - sk_sp makeWrappedSurfaceContext(sk_sp proxy); + sk_sp makeWrappedSurfaceContext(sk_sp proxy, + sk_sp); sk_sp makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc, SkBackingFit dstFit, diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index 515e26e92b..3a7110ef52 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -238,16 +238,16 @@ sk_sp GrDrawingManager::makeRenderTargetContext( return nullptr; } - sk_sp rtp(sk_ref_sp(sProxy->asRenderTargetProxy())); - // SkSurface catches bad color space usage at creation. This check handles anything that slips // by, including internal usage. We allow a null color space here, for read/write pixels and // other special code paths. If a color space is provided, though, enforce all other rules. - if (colorSpace && !SkSurface_Gpu::Valid(fContext, rtp->config(), colorSpace.get())) { + if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) { SkDEBUGFAIL("Invalid config and colorspace combination"); return nullptr; } + sk_sp rtp(sk_ref_sp(sProxy->asRenderTargetProxy())); + bool useDIF = false; if (surfaceProps) { useDIF = surfaceProps->isUseDeviceIndependentFonts(); @@ -276,16 +276,27 @@ sk_sp GrDrawingManager::makeRenderTargetContext( fSingleOwner)); } -sk_sp GrDrawingManager::makeTextureContext(sk_sp sProxy) { +sk_sp GrDrawingManager::makeTextureContext(sk_sp sProxy, + sk_sp colorSpace) { if (this->wasAbandoned() || !sProxy->asTextureProxy()) { return nullptr; } + // SkSurface catches bad color space usage at creation. This check handles anything that slips + // by, including internal usage. We allow a null color space here, for read/write pixels and + // other special code paths. If a color space is provided, though, enforce all other rules. + if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) { + SkDEBUGFAIL("Invalid config and colorspace combination"); + return nullptr; + } + // GrTextureRenderTargets should always be using GrRenderTargetContext SkASSERT(!sProxy->asRenderTargetProxy()); sk_sp textureProxy(sk_ref_sp(sProxy->asTextureProxy())); return sk_sp(new GrTextureContext(fContext, this, std::move(textureProxy), - fContext->getAuditTrail(), fSingleOwner)); + std::move(colorSpace), + fContext->getAuditTrail(), + fSingleOwner)); } diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h index 9a05215f5b..061e878793 100644 --- a/src/gpu/GrDrawingManager.h +++ b/src/gpu/GrDrawingManager.h @@ -39,7 +39,7 @@ public: sk_sp makeRenderTargetContext(sk_sp, sk_sp, const SkSurfaceProps*); - sk_sp makeTextureContext(sk_sp); + sk_sp makeTextureContext(sk_sp, sk_sp); // The caller automatically gets a ref on the returned opList. It must // be balanced by an unref call. diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index b0d941b273..39d5597ab6 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -81,15 +81,13 @@ GrRenderTargetContext::GrRenderTargetContext(GrContext* context, const SkSurfaceProps* surfaceProps, GrAuditTrail* auditTrail, GrSingleOwner* singleOwner) - : GrSurfaceContext(context, auditTrail, singleOwner) + : GrSurfaceContext(context, std::move(colorSpace), auditTrail, singleOwner) , fDrawingManager(drawingMgr) , fRenderTargetProxy(std::move(rtp)) , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList())) , fInstancedPipelineInfo(fRenderTargetProxy.get()) - , fColorSpace(std::move(colorSpace)) , fColorXformFromSRGB(nullptr) - , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) -{ + , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) { if (fColorSpace) { // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); @@ -158,6 +156,56 @@ bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy, return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint); } +// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext? +bool GrRenderTargetContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer, + size_t dstRowBytes, int x, int y) { + // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels + GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps()); + if (kUnknown_GrPixelConfig == config) { + return false; + } + + uint32_t flags = 0; + if (kUnpremul_SkAlphaType == dstInfo.alphaType()) { + flags = GrContext::kUnpremul_PixelOpsFlag; + } + + // Deferral of the VRAM resources must end in this instance anyway + sk_sp rt( + sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); + if (!rt) { + return false; + } + + return rt->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(), + config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags); +} + +// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext? +bool GrRenderTargetContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer, + size_t srcRowBytes, int x, int y) { + // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels + GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps()); + if (kUnknown_GrPixelConfig == config) { + return false; + } + uint32_t flags = 0; + if (kUnpremul_SkAlphaType == srcInfo.alphaType()) { + flags = GrContext::kUnpremul_PixelOpsFlag; + } + + // Deferral of the VRAM resources must end in this instance anyway + sk_sp rt( + sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); + if (!rt) { + return false; + } + + return rt->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(), + config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags); +} + + void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, SkScalar y, @@ -1267,53 +1315,6 @@ void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip, this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); } -bool GrRenderTargetContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer, - size_t dstRowBytes, int x, int y) { - // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels - GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps()); - if (kUnknown_GrPixelConfig == config) { - return false; - } - - uint32_t flags = 0; - if (kUnpremul_SkAlphaType == dstInfo.alphaType()) { - flags = GrContext::kUnpremul_PixelOpsFlag; - } - - // Deferral of the VRAM resources must end in this instance anyway - sk_sp rt( - sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); - if (!rt) { - return false; - } - - return rt->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(), - config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags); -} - -bool GrRenderTargetContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer, - size_t srcRowBytes, int x, int y) { - // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels - GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps()); - if (kUnknown_GrPixelConfig == config) { - return false; - } - uint32_t flags = 0; - if (kUnpremul_SkAlphaType == srcInfo.alphaType()) { - flags = GrContext::kUnpremul_PixelOpsFlag; - } - - // Deferral of the VRAM resources must end in this instance anyway - sk_sp rt( - sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); - if (!rt) { - return false; - } - - return rt->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(), - config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags); -} - // Can 'path' be drawn as a pair of filled nested rectangles? static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) { diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp index 682233bd1c..f8c1cbcc27 100644 --- a/src/gpu/GrSurfaceContext.cpp +++ b/src/gpu/GrSurfaceContext.cpp @@ -15,9 +15,11 @@ // stack. When this occurs with a closed GrOpList, a new one will be allocated // when the renderTargetContext attempts to use it (via getOpList). GrSurfaceContext::GrSurfaceContext(GrContext* context, + sk_sp colorSpace, GrAuditTrail* auditTrail, GrSingleOwner* singleOwner) : fContext(context) + , fColorSpace(std::move(colorSpace)) , fAuditTrail(auditTrail) #ifdef SK_DEBUG , fSingleOwner(singleOwner) diff --git a/src/gpu/GrTextureContext.cpp b/src/gpu/GrTextureContext.cpp index 9f61551270..7ca1e54bef 100644 --- a/src/gpu/GrTextureContext.cpp +++ b/src/gpu/GrTextureContext.cpp @@ -19,9 +19,10 @@ GrTextureContext::GrTextureContext(GrContext* context, GrDrawingManager* drawingMgr, sk_sp textureProxy, + sk_sp colorSpace, GrAuditTrail* auditTrail, GrSingleOwner* singleOwner) - : GrSurfaceContext(context, auditTrail, singleOwner) + : GrSurfaceContext(context, std::move(colorSpace), auditTrail, singleOwner) , fDrawingManager(drawingMgr) , fTextureProxy(std::move(textureProxy)) , fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList())) { @@ -75,11 +76,11 @@ bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy, if (!src) { return false; } - -#ifndef ENABLE_MDB - // We can't yet fully defer copies to textures, so GrTextureContext::copySurface will - // execute the copy immediately. Ensure the data is ready. - src->flushWrites(); + +#ifndef ENABLE_MDB + // We can't yet fully defer copies to textures, so GrTextureContext::copySurface will + // execute the copy immediately. Ensure the data is ready. + src->flushWrites(); #endif // TODO: this needs to be fixed up since it ends the deferrable of the GrTexture @@ -100,3 +101,50 @@ bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy, return result; } + +// TODO: move this (and GrRenderTargetContext::onReadPixels) to GrSurfaceContext? +bool GrTextureContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer, + size_t dstRowBytes, int x, int y) { + // TODO: teach GrTexture to take ImageInfo directly to specify the src pixels + GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps()); + if (kUnknown_GrPixelConfig == config) { + return false; + } + + uint32_t flags = 0; + if (kUnpremul_SkAlphaType == dstInfo.alphaType()) { + flags = GrContext::kUnpremul_PixelOpsFlag; + } + + // Deferral of the VRAM resources must end in this instance anyway + sk_sp tex(sk_ref_sp(fTextureProxy->instantiate(fContext->textureProvider()))); + if (!tex) { + return false; + } + + return tex->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(), + config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags); +} + +// TODO: move this (and GrRenderTargetContext::onReadPixels) to GrSurfaceContext? +bool GrTextureContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer, + size_t srcRowBytes, int x, int y) { + // TODO: teach GrTexture to take ImageInfo directly to specify the src pixels + GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps()); + if (kUnknown_GrPixelConfig == config) { + return false; + } + uint32_t flags = 0; + if (kUnpremul_SkAlphaType == srcInfo.alphaType()) { + flags = GrContext::kUnpremul_PixelOpsFlag; + } + + // Deferral of the VRAM resources must end in this instance anyway + sk_sp tex(sk_ref_sp(fTextureProxy->instantiate(fContext->textureProvider()))); + if (!tex) { + return false; + } + + return tex->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(), + config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags); +} diff --git a/src/gpu/text/GrAtlasGlyphCache.cpp b/src/gpu/text/GrAtlasGlyphCache.cpp index e51f6cc381..5b71a072df 100644 --- a/src/gpu/text/GrAtlasGlyphCache.cpp +++ b/src/gpu/text/GrAtlasGlyphCache.cpp @@ -125,7 +125,8 @@ static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* } sk_sp sContext(context->contextPriv().makeWrappedSurfaceContext( - sk_ref_sp(sProxy))); + sk_ref_sp(sProxy), + nullptr)); if (!sContext || !sContext->asDeferredTexture()) { return false; } diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index b56b1bab15..02f53e7104 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -91,6 +91,10 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst, SkColorSpace* dstColorSpace, return true; } +sk_sp SkImage_Gpu::refProxy() const { + return GrSurfaceProxy::MakeWrapped(fTexture); +} + GrTexture* SkImage_Gpu::asTextureRef(GrContext* ctx, const GrSamplerParams& params, SkColorSpace* dstColorSpace, sk_sp* texColorSpace) const { diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h index 2098864ae3..2d6f3bd831 100644 --- a/src/image/SkImage_Gpu.h +++ b/src/image/SkImage_Gpu.h @@ -43,6 +43,7 @@ public: sk_sp*) const override; sk_sp onMakeSubset(const SkIRect&) const override; + sk_sp refProxy() const; GrTexture* peekTexture() const override { return fTexture.get(); } sk_sp refPinnedTexture(uint32_t* uniqueID) const override { *uniqueID = this->uniqueID(); @@ -51,6 +52,9 @@ public: bool onReadPixels(const SkImageInfo&, void* dstPixels, size_t dstRowBytes, int srcX, int srcY, CachingHint) const override; + GrContext* context() { return fTexture->getContext(); } + sk_sp refColorSpace() { return fColorSpace; } + private: sk_sp fTexture; const SkAlphaType fAlphaType; diff --git a/tests/CopySurfaceTest.cpp b/tests/CopySurfaceTest.cpp index 951d27249f..efb6b2d43d 100644 --- a/tests/CopySurfaceTest.cpp +++ b/tests/CopySurfaceTest.cpp @@ -91,7 +91,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) { } sk_sp sContext = - context->contextPriv().makeWrappedSurfaceContext(dst); + context->contextPriv().makeWrappedSurfaceContext(dst, nullptr); bool result = sContext->copy(src.get(), srcRect, dstPoint); diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp index 1f04de5903..29aee9ccf9 100644 --- a/tests/SurfaceTest.cpp +++ b/tests/SurfaceTest.cpp @@ -20,6 +20,7 @@ #if SK_SUPPORT_GPU #include "GrContext.h" +#include "GrContextPriv.h" #include "GrRenderTargetContext.h" #include "GrGpu.h" #include "GrResourceProvider.h" @@ -626,7 +627,7 @@ static sk_sp create_gpu_surface_backend_texture_as_render_target( } static void test_surface_clear(skiatest::Reporter* reporter, sk_sp surface, - std::function grSurfaceGetter, + std::function(SkSurface*)> grSurfaceGetter, uint32_t expectedValue) { if (!surface) { ERRORF(reporter, "Could not create GPU SkSurface."); @@ -637,13 +638,15 @@ static void test_surface_clear(skiatest::Reporter* reporter, sk_sp su std::unique_ptr pixels(new uint32_t[w * h]); sk_memset32(pixels.get(), ~expectedValue, w * h); - sk_sp grSurface(SkSafeRef(grSurfaceGetter(surface.get()))); - if (!grSurface) { + sk_sp grSurfaceContext(grSurfaceGetter(surface.get())); + if (!grSurfaceContext) { ERRORF(reporter, "Could access render target of GPU SkSurface."); return; } surface.reset(); - grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get()); + + SkImageInfo ii = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType); + grSurfaceContext->readPixels(ii, pixels.get(), 0, 0, 0); for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { uint32_t pixel = pixels.get()[y * w + x]; @@ -666,16 +669,21 @@ static void test_surface_clear(skiatest::Reporter* reporter, sk_sp su DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) { GrContext* context = ctxInfo.grContext(); - std::function grSurfaceGetters[] = { + std::function(SkSurface*)> grSurfaceContextGetters[] = { [] (SkSurface* s){ - GrRenderTargetContext* rtc = - s->getCanvas()->internal_private_accessTopLayerRenderTargetContext(); - return rtc->accessRenderTarget(); }, - [] (SkSurface* s){ sk_sp i(s->makeImageSnapshot()); - return as_IB(i)->peekTexture(); } + return sk_ref_sp(s->getCanvas()->internal_private_accessTopLayerRenderTargetContext()); + }, + [] (SkSurface* s){ + sk_sp i(s->makeImageSnapshot()); + SkImage_Gpu* gpuImage = (SkImage_Gpu *) as_IB(i); + sk_sp proxy = gpuImage->refProxy(); + GrContext* context = gpuImage->context(); + return context->contextPriv().makeWrappedSurfaceContext(std::move(proxy), + gpuImage->refColorSpace()); + } }; - for (auto grSurfaceGetter : grSurfaceGetters) { + for (auto grSurfaceGetter : grSurfaceContextGetters) { // Test that non-wrapped RTs are created clear. for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) { auto surface = surface_func(context, kPremul_SkAlphaType, nullptr);