From 24f636fc9e5b0b869a84004a1afe877884c406a1 Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Mon, 21 Nov 2016 09:03:54 -0500 Subject: [PATCH] Cherry pick fuzzer fixes back to M56 This cherry-pick combines 3 fuzzer-fix CLs: These two rolled into Chrome in https://codereview.chromium.org/2511733006 at 433297 on 11/18 https://skia-review.googlesource.com/c/4961/ (Remove accessRenderTarget call in SkGpuDevice ctor) https://skia-review.googlesource.com/c/4929/ (Guard against instantiate & accessRenderTarget failures) This one rolled into Chrome in https://codereview.chromium.org/2516183002 at 433454 on 11/20 https://skia-review.googlesource.com/c/4991/ (Add handling for instantiate failure up the call stack) Together they address the fuzzer bugs: crbug.com/665681 P1 (Crash in SkSpecialImage_Gpu::onAsTextureRef) crbug.com/665621 P1 (Crash in GrGpuCommandBuffer::draw) crbug.com/665500 P1 (Crash in GrDrawBatch::renderTargetUniqueID) The fuzzer bugs were fixed by the first two patches but the third is going to be necessary too. BUG=665681,665500,665621 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5081 NOTREECHECKS=true NOTRY=true NOPRESUBMIT=true Change-Id: I3a8b70eae29ac11608e062e66bc26c2208c1dfb3 Reviewed-on: https://skia-review.googlesource.com/5081 Reviewed-by: Brian Salomon Reviewed-by: Heather Miller Commit-Queue: Robert Phillips --- include/gpu/GrRenderTargetContext.h | 4 ++++ src/core/SkBlurImageFilter.cpp | 4 +++- src/core/SkCanvas.cpp | 8 +++++--- src/core/SkSpecialImage.cpp | 13 ++++++++++++- src/core/SkSpecialSurface.cpp | 13 ++++++++----- src/effects/SkBlurMaskFilter.cpp | 3 +++ src/effects/SkMorphologyImageFilter.cpp | 17 ++++++++++------- src/gpu/GrClipStackClip.cpp | 10 +++++++--- src/gpu/GrContext.cpp | 4 ++++ src/gpu/GrDrawingManager.cpp | 3 +++ src/gpu/GrPipeline.cpp | 5 ++++- src/gpu/GrRenderTargetContext.cpp | 25 ++++++++++++++++++++++++- src/gpu/GrRenderTargetOpList.cpp | 11 +++++++++++ src/gpu/SkGpuDevice.cpp | 23 +++++++++++++---------- src/gpu/SkGpuDevice.h | 7 +++---- src/gpu/effects/GrConfigConversionEffect.cpp | 3 +++ src/image/SkImage_Gpu.cpp | 4 ++++ src/image/SkSurface_Gpu.cpp | 20 ++++++++++++++++---- 18 files changed, 137 insertions(+), 40 deletions(-) diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h index a3869a3..d1896db 100644 --- a/include/gpu/GrRenderTargetContext.h +++ b/include/gpu/GrRenderTargetContext.h @@ -354,6 +354,10 @@ public: GrTextureProxy* asDeferredTexture(); sk_sp asTexture() { + if (!this->accessRenderTarget()) { + return nullptr; + } + // TODO: usage of this entry point needs to be reduced and potentially eliminated // since it ends the deferral of the GrRenderTarget's allocation // It's usage should migrate to asDeferredTexture diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp index d531b44..7590fdc 100644 --- a/src/core/SkBlurImageFilter.cpp +++ b/src/core/SkBlurImageFilter.cpp @@ -136,7 +136,9 @@ sk_sp SkBlurImageFilterImpl::onFilterImage(SkSpecialImage* sourc if (source->isTextureBacked()) { GrContext* context = source->getContext(); sk_sp inputTexture(input->asTextureRef(context)); - SkASSERT(inputTexture); + if (!inputTexture) { + return nullptr; + } if (0 == sigma.x() && 0 == sigma.y()) { offset->fX = inputBounds.x(); diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index eddf106..aa74a64 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1419,9 +1419,11 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa paint = &looper.paint(); SkImageFilter* filter = paint->getImageFilter(); SkIPoint pos = { x - iter.getX(), y - iter.getY() }; - sk_sp specialImage; - if (filter && (specialImage = srcDev->snapSpecial())) { - dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint); + if (filter) { + sk_sp specialImage = srcDev->snapSpecial(); + if (specialImage) { + dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint); + } } else { dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); } diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index f188781..c97eb01 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -390,6 +390,9 @@ public: // TODO: add GrTextureProxy-backed SkImage_Gpus GrSurface* surf = fSurfaceProxy->instantiate(fContext->textureProvider()); + if (!surf) { + return; + } // TODO: In this instance we know we're going to draw a sub-portion of the backing // texture into the canvas so it is okay to wrap it in an SkImage. This poses @@ -411,7 +414,9 @@ public: // This entry point should go away in favor of asTextureProxy sk_sp onAsTextureRef(GrContext* context) const override { GrSurface* surf = fSurfaceProxy->instantiate(context->textureProvider()); - + if (!surf) { + return nullptr; + } return sk_ref_sp(surf->asTexture()); } @@ -436,6 +441,9 @@ public: // Reading back to an SkBitmap ends deferral GrSurface* surface = fSurfaceProxy->instantiate(fContext->textureProvider()); + if (!surface) { + return false; + } if (!surface->readPixels(0, 0, dst->width(), dst->height(), kSkia8888_GrPixelConfig, dst->getPixels(), dst->rowBytes())) { @@ -477,6 +485,9 @@ public: sk_sp onMakeTightSubset(const SkIRect& subset) const override { // TODO: add GrTextureProxy-backed SkImage_Gpus GrSurface* surf = fSurfaceProxy->instantiate(fContext->textureProvider()); + if (!surf) { + return nullptr; + } if (0 == subset.fLeft && 0 == subset.fTop && fSurfaceProxy->width() == subset.width() && diff --git a/src/core/SkSpecialSurface.cpp b/src/core/SkSpecialSurface.cpp index b490421..956300c 100644 --- a/src/core/SkSpecialSurface.cpp +++ b/src/core/SkSpecialSurface.cpp @@ -115,13 +115,12 @@ sk_sp SkSpecialSurface::MakeRaster(const SkImageInfo& info, class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { public: - SkSpecialSurface_Gpu(sk_sp renderTargetContext, - int width, int height, - const SkIRect& subset) + SkSpecialSurface_Gpu(GrContext* context, sk_sp renderTargetContext, + int width, int height, const SkIRect& subset) : INHERITED(subset, &renderTargetContext->surfaceProps()) , fRenderTargetContext(std::move(renderTargetContext)) { - sk_sp device(SkGpuDevice::Make(fRenderTargetContext, width, height, + sk_sp device(SkGpuDevice::Make(context, fRenderTargetContext, width, height, SkGpuDevice::kUninit_InitContents)); if (!device) { return; @@ -137,6 +136,9 @@ public: ~SkSpecialSurface_Gpu() override { } sk_sp onMakeImageSnapshot() override { + if (!fRenderTargetContext->asTexture()) { + return nullptr; + } sk_sp tmp(SkSpecialImage::MakeFromGpu( this->subset(), kNeedNewImageUniqueID_SpecialImage, @@ -169,7 +171,8 @@ sk_sp SkSpecialSurface::MakeRenderTarget(GrContext* context, const SkIRect subset = SkIRect::MakeWH(width, height); - return sk_make_sp(std::move(renderTargetContext), width, height, subset); + return sk_make_sp(context, std::move(renderTargetContext), + width, height, subset); } #endif diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 0a98fa8..24de5c6 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -1135,6 +1135,9 @@ static sk_sp find_or_create_rrect_blur_mask(GrContext* context, rtc->drawRRect(GrNoClip(), grPaint, SkMatrix::I(), rrectToDraw, GrStyle::SimpleFill()); sk_sp srcTexture(rtc->asTexture()); + if (!srcTexture) { + return nullptr; + } sk_sp rtc2(SkGpuBlurUtils::GaussianBlur(context, srcTexture.get(), nullptr, diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index cd35d65..28b860f 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -399,10 +399,11 @@ static void apply_morphology_rect(GrTextureProvider* provider, Gr1DKernelEffect::Direction direction) { GrPaint paint; paint.setGammaCorrect(renderTargetContext->isGammaCorrect()); - paint.addColorFragmentProcessor(GrMorphologyEffect::Make(textureProxy->instantiate(provider), - direction, - radius, - morphType, + GrTexture* tex = textureProxy->instantiate(provider); + if (!tex) { + return; + } + paint.addColorFragmentProcessor(GrMorphologyEffect::Make(tex, direction, radius, morphType, bounds)); paint.setPorterDuffXPFactory(SkBlendMode::kSrc); renderTargetContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), @@ -420,9 +421,11 @@ static void apply_morphology_rect_no_bounds(GrTextureProvider* provider, Gr1DKernelEffect::Direction direction) { GrPaint paint; paint.setGammaCorrect(renderTargetContext->isGammaCorrect()); - paint.addColorFragmentProcessor(GrMorphologyEffect::Make(textureProxy->instantiate(provider), - direction, radius, - morphType)); + GrTexture* tex = textureProxy->instantiate(provider); + if (!tex) { + return; + } + paint.addColorFragmentProcessor(GrMorphologyEffect::Make(tex, direction, radius, morphType)); paint.setPorterDuffXPFactory(SkBlendMode::kSrc); renderTargetContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), SkRect::Make(srcRect)); diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index 133c4f7..0af6c03 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -340,8 +340,6 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar result = CreateSoftwareClipMask(context->textureProvider(), reducedClip); } else { result = CreateAlphaClipMask(context, reducedClip); - // If createAlphaClipMask fails it means UseSWOnlyPath has a bug - SkASSERT(result); } if (result) { @@ -356,6 +354,9 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar } GrRenderTarget* rt = renderTargetContext->accessRenderTarget(); + if (!rt) { + return true; + } // use the stencil clip if we can't represent the clip as a rectangle. if (!context->resourceProvider()->attachStencilAttachment(rt)) { @@ -413,7 +414,10 @@ sk_sp GrClipStackClip::CreateAlphaClipMask(GrContext* context, } sk_sp texture(rtc->asTexture()); - SkASSERT(texture); + if (!texture) { + return nullptr; + } + texture->resourcePriv().setUniqueKey(key); return texture; } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 71203d6..4994ae0 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -494,6 +494,10 @@ bool GrContext::readSurfacePixels(GrSurface* src, } } + if (!surfaceToRead) { + return false; + } + if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) { return false; } diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index f16f861..5267df3 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -235,6 +235,9 @@ sk_sp GrDrawingManager::makeRenderTargetContext( rtp->isStencilBufferMultisampled()) { // TODO: defer stencil buffer attachment for PathRenderingDrawContext sk_sp rt(sk_ref_sp(rtp->instantiate(fContext->textureProvider()))); + if (!rt) { + return nullptr; + } GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt.get()); if (sb) { return sk_sp(new GrPathRenderingRenderTargetContext( diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index 875c50e..976deec 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -23,7 +23,10 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args, const GrPipelineBuilder& builder = *args.fPipelineBuilder; const GrUserStencilSettings* userStencil = builder.getUserStencil(); GrRenderTarget* rt = args.fRenderTargetContext->accessRenderTarget(); - + if (!rt) { + return nullptr; + } + GrPipeline* pipeline = new (memory) GrPipeline; pipeline->fRenderTarget.reset(rt); SkASSERT(pipeline->fRenderTarget); diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 3bc6ad3..e311c3d 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -146,6 +146,9 @@ bool GrRenderTargetContext::copySurface(GrSurface* src, const SkIRect& srcRect, // TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget sk_sp rt( sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); + if (!rt) { + return false; + } return this->getOpList()->copySurface(rt.get(), src, srcRect, dstPoint); } @@ -208,6 +211,9 @@ void GrRenderTargetContext::discard() { // TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget sk_sp rt( sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); + if (!rt) { + return; + } this->getOpList()->discard(rt.get()); } @@ -264,8 +270,13 @@ void GrRenderTargetContext::internalClear(const GrFixedClip& clip, this->drawRect(clip, paint, SkMatrix::I(), clearRect); } else if (isFull) { - this->getOpList()->fullClear(this->accessRenderTarget(), color); + if (this->accessRenderTarget()) { + this->getOpList()->fullClear(this->accessRenderTarget(), color); + } } else { + if (!this->accessRenderTarget()) { + return; + } sk_sp batch(GrClearBatch::Make(clip, color, this->accessRenderTarget())); if (!batch) { return; @@ -592,6 +603,9 @@ void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool i "GrRenderTargetContextPriv::clearStencilClip"); AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); + if (!fRenderTargetContext->accessRenderTarget()) { + return; + } fRenderTargetContext->getOpList()->clearStencilClip(clip, insideStencilMask, fRenderTargetContext->accessRenderTarget()); } @@ -1144,6 +1158,9 @@ void GrRenderTargetContext::prepareForExternalIO() { // Deferral of the VRAM resources must end in this instance anyway sk_sp rt( sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); + if (!rt) { + return; + } ASSERT_OWNED_RESOURCE(rt); @@ -1185,6 +1202,9 @@ bool GrRenderTargetContext::readPixels(const SkImageInfo& dstInfo, void* dstBuff // 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(x, y, dstInfo.width(), dstInfo.height(), config, dstBuffer, dstRowBytes, flags); @@ -1205,6 +1225,9 @@ bool GrRenderTargetContext::writePixels(const SkImageInfo& srcInfo, const void* // 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(x, y, srcInfo.width(), srcInfo.height(), config, srcBuffer, srcRowBytes, flags); diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp index 72a29ab..aab71f9 100644 --- a/src/gpu/GrRenderTargetOpList.cpp +++ b/src/gpu/GrRenderTargetOpList.cpp @@ -301,6 +301,10 @@ void GrRenderTargetOpList::drawBatch(const GrPipelineBuilder& pipelineBuilder, } if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) { + if (!renderTargetContext->accessRenderTarget()) { + return; + } + if (!fResourceProvider->attachStencilAttachment( renderTargetContext->accessRenderTarget())) { SkDebugf("ERROR creating stencil attachment. Draw skipped.\n"); @@ -341,6 +345,10 @@ void GrRenderTargetOpList::drawBatch(const GrPipelineBuilder& pipelineBuilder, args.fScissor = &appliedClip.scissorState(); args.fWindowRectsState = &appliedClip.windowRectsState(); args.fHasStencilClip = appliedClip.hasStencilClip(); + if (!renderTargetContext->accessRenderTarget()) { + return; + } + if (!this->setupDstReadIfNecessary(pipelineBuilder, renderTargetContext->accessRenderTarget(), clip, args.fOpts, &args.fDstTexture, batch->bounds())) { @@ -382,6 +390,9 @@ void GrRenderTargetOpList::stencilPath(GrRenderTargetContext* renderTargetContex // attempt this in a situation that would require coverage AA. SkASSERT(!appliedClip.clipCoverageFragmentProcessor()); + if (!renderTargetContext->accessRenderTarget()) { + return; + } GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment( renderTargetContext->accessRenderTarget()); if (!stencilAttachment) { diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 1fbc953..b7d276a 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -87,7 +87,8 @@ bool SkGpuDevice::CheckAlphaTypeAndGetFlags( return true; } -sk_sp SkGpuDevice::Make(sk_sp renderTargetContext, +sk_sp SkGpuDevice::Make(GrContext* context, + sk_sp renderTargetContext, int width, int height, InitContents init) { if (!renderTargetContext || renderTargetContext->wasAbandoned()) { @@ -97,8 +98,8 @@ sk_sp SkGpuDevice::Make(sk_sp renderTargetCo if (!CheckAlphaTypeAndGetFlags(nullptr, init, &flags)) { return nullptr; } - return sk_sp(new SkGpuDevice(std::move(renderTargetContext), width, height, - flags)); + return sk_sp(new SkGpuDevice(context, std::move(renderTargetContext), + width, height, flags)); } sk_sp SkGpuDevice::Make(GrContext* context, SkBudgeted budgeted, @@ -117,7 +118,7 @@ sk_sp SkGpuDevice::Make(GrContext* context, SkBudgeted budgeted, return nullptr; } - return sk_sp(new SkGpuDevice(std::move(renderTargetContext), + return sk_sp(new SkGpuDevice(context, std::move(renderTargetContext), info.width(), info.height(), flags)); } @@ -131,11 +132,11 @@ static SkImageInfo make_info(GrRenderTargetContext* context, int w, int h, bool sk_ref_sp(context->getColorSpace())); } -SkGpuDevice::SkGpuDevice(sk_sp renderTargetContext, int width, int height, - unsigned flags) +SkGpuDevice::SkGpuDevice(GrContext* context, sk_sp renderTargetContext, + int width, int height, unsigned flags) : INHERITED(make_info(renderTargetContext.get(), width, height, SkToBool(flags & kIsOpaque_Flag)), renderTargetContext->surfaceProps()) - , fContext(SkRef(renderTargetContext->accessRenderTarget()->getContext())) + , fContext(SkRef(context)) , fRenderTargetContext(std::move(renderTargetContext)) { fSize.set(width, height); @@ -1158,6 +1159,9 @@ void SkGpuDevice::drawSpecial(const SkDraw& draw, SkASSERT(result->isTextureBacked()); sk_sp texture = result->asTextureRef(fContext.get()); + if (!texture) { + return; + } SkPaint tmpUnfiltered(paint); tmpUnfiltered.setImageFilter(nullptr); @@ -1811,9 +1815,8 @@ SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint // Skia's convention is to only clear a device if it is non-opaque. InitContents init = cinfo.fInfo.isOpaque() ? kUninit_InitContents : kClear_InitContents; - return SkGpuDevice::Make(std::move(rtc), - cinfo.fInfo.width(), cinfo.fInfo.height(), - init).release(); + return SkGpuDevice::Make(fContext.get(), std::move(rtc), + cinfo.fInfo.width(), cinfo.fInfo.height(), init).release(); } sk_sp SkGpuDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) { diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index ca5be45..b81da4e 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -42,9 +42,8 @@ public: * Creates an SkGpuDevice from a GrRenderTargetContext whose backing width/height is * different than its actual width/height (e.g., approx-match scratch texture). */ - static sk_sp Make(sk_sp renderTargetContext, - int width, int height, - InitContents); + static sk_sp Make(GrContext*, sk_sp renderTargetContext, + int width, int height, InitContents); /** * New device that will create an offscreen renderTarget based on the ImageInfo and @@ -148,7 +147,7 @@ private: static bool CheckAlphaTypeAndGetFlags(const SkImageInfo* info, InitContents init, unsigned* flags); - SkGpuDevice(sk_sp, int width, int height, unsigned flags); + SkGpuDevice(GrContext*, sk_sp, int width, int height, unsigned flags); SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp index db70017..545d30b 100644 --- a/src/gpu/effects/GrConfigConversionEffect.cpp +++ b/src/gpu/effects/GrConfigConversionEffect.cpp @@ -220,6 +220,9 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data. // We then verify that two reads produced the same values. + if (!readRTC->asTexture()) { + continue; + } GrPaint paint1; GrPaint paint2; GrPaint paint3; diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index a006e14..c75e36b 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -270,6 +270,10 @@ static sk_sp make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpac const SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); renderTargetContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect); + + if (!renderTargetContext->accessRenderTarget()) { + return nullptr; + } ctx->flushSurfaceWrites(renderTargetContext->accessRenderTarget()); return sk_make_sp(width, height, kNeedNewImageUniqueID, kOpaque_SkAlphaType, renderTargetContext->asTexture(), diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp index 13bbd4f..f99d3c2 100644 --- a/src/image/SkSurface_Gpu.cpp +++ b/src/image/SkSurface_Gpu.cpp @@ -46,6 +46,9 @@ static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface, GrBackendObject SkSurface_Gpu::onGetTextureHandle(BackendHandleAccess access) { GrRenderTarget* rt = prepare_rt_for_external_access(this, access); + if (!rt) { + return 0; + } GrTexture* texture = rt->asTexture(); if (texture) { return texture->getTextureHandle(); @@ -55,6 +58,9 @@ GrBackendObject SkSurface_Gpu::onGetTextureHandle(BackendHandleAccess access) { bool SkSurface_Gpu::onGetRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { GrRenderTarget* rt = prepare_rt_for_external_access(this, access); + if (!rt) { + return false; + } *obj = rt->getRenderTargetHandle(); return true; } @@ -77,7 +83,10 @@ sk_sp SkSurface_Gpu::onNewSurface(const SkImageInfo& info) { sk_sp SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, SkCopyPixelsMode cpm) { GrRenderTarget* rt = fDevice->accessRenderTargetContext()->accessRenderTarget(); - SkASSERT(rt); + if (!rt) { + return nullptr; + } + GrTexture* tex = rt->asTexture(); sk_sp copy; // If the original render target is a buffer originally created by the client, then we don't @@ -111,6 +120,9 @@ sk_sp SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, SkCopyPixe // doesn't force an OpenGL flush. void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) { GrRenderTarget* rt = fDevice->accessRenderTargetContext()->accessRenderTarget(); + if (!rt) { + return; + } // are we sharing our render target with the image? Note this call should never create a new // image because onCopyOnWrite is only called when there is a cached image. sk_sp image(this->refCachedImage(SkBudgeted::kNo, kNo_ForceUnique)); @@ -201,7 +213,7 @@ sk_sp SkSurface::MakeFromBackendTexture(GrContext* context, return nullptr; } - sk_sp device(SkGpuDevice::Make(std::move(rtc), desc.fWidth, desc.fHeight, + sk_sp device(SkGpuDevice::Make(context, std::move(rtc), desc.fWidth, desc.fHeight, SkGpuDevice::kUninit_InitContents)); if (!device) { return nullptr; @@ -228,7 +240,7 @@ sk_sp SkSurface::MakeFromBackendRenderTarget(GrContext* context, return nullptr; } - sk_sp device(SkGpuDevice::Make(std::move(rtc), desc.fWidth, desc.fHeight, + sk_sp device(SkGpuDevice::Make(context, std::move(rtc), desc.fWidth, desc.fHeight, SkGpuDevice::kUninit_InitContents)); if (!device) { return nullptr; @@ -257,7 +269,7 @@ sk_sp SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* cont return nullptr; } - sk_sp device(SkGpuDevice::Make(std::move(rtc), desc.fWidth, desc.fHeight, + sk_sp device(SkGpuDevice::Make(context, std::move(rtc), desc.fWidth, desc.fHeight, SkGpuDevice::kUninit_InitContents)); if (!device) { return nullptr; -- 2.7.4