Index: src/core/SkSpecialSurface.cpp |
diff --git a/src/core/SkSpecialSurface.cpp b/src/core/SkSpecialSurface.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5d57dcfd4fc0bea5c1677e43955ef74c7b769de5 |
--- /dev/null |
+++ b/src/core/SkSpecialSurface.cpp |
@@ -0,0 +1,177 @@ |
+/* |
+ * 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; } |
+ |
+ virtual SkSpecialImage* onNewImageSnapshot() = 0; |
+ |
+protected: |
+ SkAutoTUnref<SkCanvas> fCanvas; // initialized by derived classes in ctors |
+ |
+private: |
+ typedef SkSpecialSurface INHERITED; |
+}; |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) { |
+ return static_cast<SkSpecialSurface_Base*>(surface); |
+} |
+ |
+SkSpecialSurface::SkSpecialSurface(const SkIRect& subset, const SkSurfaceProps* props) |
+ : fProps(SkSurfacePropsCopyOrDefault(props)) |
+ , fSubset(subset) { |
+ SkASSERT(fSubset.width() > 0); |
+ SkASSERT(fSubset.height() > 0); |
+} |
+ |
+SkCanvas* SkSpecialSurface::getCanvas() { |
+ return as_SB(this)->onGetCanvas(); |
+} |
+ |
+SkSpecialImage* SkSpecialSurface::newImageSnapshot() { |
+ SkSpecialImage* image = as_SB(this)->onNewImageSnapshot(); |
+ as_SB(this)->reset(); |
+ return SkSafeRef(image); // the caller will call unref() to balance this |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+#include "SkMallocPixelRef.h" |
+ |
+class SkSpecialSurface_Raster : public SkSpecialSurface_Base { |
+public: |
+ SkSpecialSurface_Raster(SkPixelRef* pr, const SkIRect& subset, const SkSurfaceProps* props) |
+ : INHERITED(subset, props) { |
+ const SkImageInfo& info = pr->info(); |
+ |
+ fBitmap.setInfo(info, info.minRowBytes()); |
+ fBitmap.setPixelRef(pr); |
+ |
+ fCanvas.reset(new SkCanvas(fBitmap)); |
+ } |
+ |
+ ~SkSpecialSurface_Raster() override { } |
+ |
+ SkSpecialImage* onNewImageSnapshot() override { |
+ return SkSpecialImage::NewFromRaster(this->subset(), fBitmap); |
+ } |
+ |
+private: |
+ SkBitmap fBitmap; |
+ |
+ typedef SkSpecialSurface_Base INHERITED; |
+}; |
+ |
+SkSpecialSurface* SkSpecialSurface::NewFromBitmap(const SkIRect& subset, SkBitmap& bm, |
+ const SkSurfaceProps* props) { |
+ return new SkSpecialSurface_Raster(bm.pixelRef(), subset, props); |
+} |
+ |
+SkSpecialSurface* SkSpecialSurface::NewRaster(const SkImageInfo& info, |
+ const SkSurfaceProps* props) { |
+ SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewZeroed(info, 0, nullptr)); |
+ if (nullptr == pr.get()) { |
+ return nullptr; |
+ } |
+ |
+ const SkIRect subset = SkIRect::MakeWH(pr->info().width(), pr->info().height()); |
+ |
+ return new SkSpecialSurface_Raster(pr, subset, props); |
+} |
+ |
+#if SK_SUPPORT_GPU |
+/////////////////////////////////////////////////////////////////////////////// |
+#include "GrContext.h" |
+#include "SkGpuDevice.h" |
+ |
+class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { |
+public: |
+ SkSpecialSurface_Gpu(GrTexture* texture, const SkIRect& subset, const SkSurfaceProps* props) |
+ : INHERITED(subset, props) |
+ , fTexture(texture) { |
+ |
+ SkASSERT(fTexture->asRenderTarget()); |
+ |
+ SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(fTexture->asRenderTarget(), props, |
+ SkGpuDevice::kUninit_InitContents)); |
+ if (!device) { |
+ return; |
+ } |
+ |
+ fCanvas.reset(new SkCanvas(device)); |
+ } |
+ |
+ ~SkSpecialSurface_Gpu() override { } |
+ |
+ SkSpecialImage* onNewImageSnapshot() override { |
+ return SkSpecialImage::NewFromGpu(this->subset(), fTexture); |
+ } |
+ |
+private: |
+ SkAutoTUnref<GrTexture> fTexture; |
+ |
+ typedef SkSpecialSurface_Base INHERITED; |
+}; |
+ |
+SkSpecialSurface* SkSpecialSurface::NewFromTexture(const SkIRect& subset, GrTexture* texture, |
+ const SkSurfaceProps* props) { |
+ if (!texture->asRenderTarget()) { |
+ return nullptr; |
+ } |
+ |
+ return new SkSpecialSurface_Gpu(texture, subset, props); |
+} |
+ |
+SkSpecialSurface* SkSpecialSurface::NewRenderTarget(GrContext* context, |
+ const GrSurfaceDesc& desc, |
+ const SkSurfaceProps* props) { |
+ if (!context || !SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag)) { |
+ return nullptr; |
+ } |
+ |
+ GrTexture* temp = context->textureProvider()->createApproxTexture(desc); |
+ if (!temp) { |
+ return nullptr; |
+ } |
+ |
+ const SkIRect subset = SkIRect::MakeWH(desc.fWidth, desc.fHeight); |
+ |
+ return new SkSpecialSurface_Gpu(temp, subset, props); |
+} |
+ |
+#else |
+ |
+SkSpecialSurface* SkSpecialSurface::NewFromTexture(const SkIRect& subset, GrTexture*, |
+ const SkSurfaceProps*) { |
+ return nullptr; |
+} |
+ |
+SkSpecialSurface* SkSpecialSurface::NewRenderTarget(GrContext* context, |
+ const GrSurfaceDesc& desc, |
+ const SkSurfaceProps* props) { |
+ return nullptr; |
+} |
+ |
+#endif |