/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file */ #include "SkCanvas.h" #include "SkSpecialImage.h" #include "SkSpecialSurface.h" #include "SkSurfacePriv.h" /////////////////////////////////////////////////////////////////////////////// class SkSpecialSurface_Base : public SkSpecialSurface { public: SkSpecialSurface_Base(const SkIRect& subset, const SkSurfaceProps* props) : INHERITED(subset, props) , fCanvas(nullptr) { } virtual ~SkSpecialSurface_Base() { } // reset is called after an SkSpecialImage has been snapped void reset() { fCanvas.reset(); } // This can return nullptr if reset has already been called or something when wrong in the ctor SkCanvas* onGetCanvas() { return fCanvas.get(); } virtual sk_sp onMakeImageSnapshot() = 0; protected: std::unique_ptr fCanvas; // initialized by derived classes in ctors private: typedef SkSpecialSurface INHERITED; }; /////////////////////////////////////////////////////////////////////////////// static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) { return static_cast(surface); } SkSpecialSurface::SkSpecialSurface(const SkIRect& subset, const SkSurfaceProps* props) : fProps(SkSurfacePropsCopyOrDefault(props).flags(), kUnknown_SkPixelGeometry) , fSubset(subset) { SkASSERT(fSubset.width() > 0); SkASSERT(fSubset.height() > 0); } SkCanvas* SkSpecialSurface::getCanvas() { return as_SB(this)->onGetCanvas(); } sk_sp SkSpecialSurface::makeImageSnapshot() { sk_sp image(as_SB(this)->onMakeImageSnapshot()); as_SB(this)->reset(); return image; // the caller gets the creation ref } /////////////////////////////////////////////////////////////////////////////// #include "SkMallocPixelRef.h" class SkSpecialSurface_Raster : public SkSpecialSurface_Base { public: SkSpecialSurface_Raster(sk_sp pr, const SkIRect& subset, const SkSurfaceProps* props) : INHERITED(subset, props) { const SkImageInfo& info = pr->info(); fBitmap.setInfo(info, info.minRowBytes()); fBitmap.setPixelRef(std::move(pr), 0, 0); fCanvas.reset(new SkCanvas(fBitmap, this->props())); fCanvas->clipRect(SkRect::Make(subset)); #ifdef SK_IS_BOT fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness #endif } ~SkSpecialSurface_Raster() override { } sk_sp onMakeImageSnapshot() override { return SkSpecialImage::MakeFromRaster(this->subset(), fBitmap, &this->props()); } private: SkBitmap fBitmap; typedef SkSpecialSurface_Base INHERITED; }; sk_sp SkSpecialSurface::MakeFromBitmap(const SkIRect& subset, SkBitmap& bm, const SkSurfaceProps* props) { return sk_make_sp(sk_ref_sp(bm.pixelRef()), subset, props); } sk_sp SkSpecialSurface::MakeRaster(const SkImageInfo& info, const SkSurfaceProps* props) { sk_sp pr(SkMallocPixelRef::NewZeroed(info, 0, nullptr)); if (nullptr == pr.get()) { return nullptr; } const SkIRect subset = SkIRect::MakeWH(pr->info().width(), pr->info().height()); return sk_make_sp(std::move(pr), subset, props); } #if SK_SUPPORT_GPU /////////////////////////////////////////////////////////////////////////////// #include "GrContext.h" #include "SkGpuDevice.h" class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { public: 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(context, fRenderTargetContext, width, height, SkGpuDevice::kUninit_InitContents)); if (!device) { return; } fCanvas.reset(new SkCanvas(device.get())); fCanvas->clipRect(SkRect::Make(subset)); #ifdef SK_IS_BOT fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness #endif } ~SkSpecialSurface_Gpu() override { } sk_sp onMakeImageSnapshot() override { if (!fRenderTargetContext->asTexture()) { return nullptr; } sk_sp tmp(SkSpecialImage::MakeDeferredFromGpu( fCanvas->getGrContext(), this->subset(), kNeedNewImageUniqueID_SpecialImage, fRenderTargetContext->asTextureProxyRef(), fRenderTargetContext->refColorSpace(), &this->props())); fRenderTargetContext = nullptr; return tmp; } private: sk_sp fRenderTargetContext; typedef SkSpecialSurface_Base INHERITED; }; sk_sp SkSpecialSurface::MakeRenderTarget(GrContext* context, int width, int height, GrPixelConfig config, sk_sp colorSpace) { if (!context) { return nullptr; } sk_sp renderTargetContext(context->makeRenderTargetContext( SkBackingFit::kApprox, width, height, config, std::move(colorSpace))); if (!renderTargetContext) { return nullptr; } const SkIRect subset = SkIRect::MakeWH(width, height); return sk_make_sp(context, std::move(renderTargetContext), width, height, subset); } #endif