1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file
6 */
7
8#include "src/core/SkSpecialSurface.h"
9
10#include <memory>
11
12#include "include/core/SkCanvas.h"
13#include "src/core/SkSpecialImage.h"
14#include "src/core/SkSurfacePriv.h"
15
16 ///////////////////////////////////////////////////////////////////////////////
17class SkSpecialSurface_Base : public SkSpecialSurface {
18public:
19 SkSpecialSurface_Base(const SkIRect& subset, const SkSurfaceProps* props)
20 : INHERITED(subset, props)
21 , fCanvas(nullptr) {
22 }
23
24 // reset is called after an SkSpecialImage has been snapped
25 void reset() { fCanvas.reset(); }
26
27 // This can return nullptr if reset has already been called or something when wrong in the ctor
28 SkCanvas* onGetCanvas() { return fCanvas.get(); }
29
30 virtual sk_sp<SkSpecialImage> onMakeImageSnapshot() = 0;
31
32protected:
33 std::unique_ptr<SkCanvas> fCanvas; // initialized by derived classes in ctors
34
35private:
36 typedef SkSpecialSurface INHERITED;
37};
38
39///////////////////////////////////////////////////////////////////////////////
40static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) {
41 return static_cast<SkSpecialSurface_Base*>(surface);
42}
43
44SkSpecialSurface::SkSpecialSurface(const SkIRect& subset,
45 const SkSurfaceProps* props)
46 : fProps(SkSurfacePropsCopyOrDefault(props).flags(), kUnknown_SkPixelGeometry)
47 , fSubset(subset) {
48 SkASSERT(fSubset.width() > 0);
49 SkASSERT(fSubset.height() > 0);
50}
51
52SkCanvas* SkSpecialSurface::getCanvas() {
53 return as_SB(this)->onGetCanvas();
54}
55
56sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() {
57 sk_sp<SkSpecialImage> image(as_SB(this)->onMakeImageSnapshot());
58 as_SB(this)->reset();
59 return image; // the caller gets the creation ref
60}
61
62///////////////////////////////////////////////////////////////////////////////
63#include "include/core/SkMallocPixelRef.h"
64
65class SkSpecialSurface_Raster : public SkSpecialSurface_Base {
66public:
67 SkSpecialSurface_Raster(const SkImageInfo& info,
68 sk_sp<SkPixelRef> pr,
69 const SkIRect& subset,
70 const SkSurfaceProps* props)
71 : INHERITED(subset, props) {
72 SkASSERT(info.width() == pr->width() && info.height() == pr->height());
73 fBitmap.setInfo(info, info.minRowBytes());
74 fBitmap.setPixelRef(std::move(pr), 0, 0);
75
76 fCanvas = std::make_unique<SkCanvas>(fBitmap, this->props());
77 fCanvas->clipRect(SkRect::Make(subset));
78#ifdef SK_IS_BOT
79 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness
80#endif
81 }
82
83 ~SkSpecialSurface_Raster() override { }
84
85 sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
86 return SkSpecialImage::MakeFromRaster(this->subset(), fBitmap, &this->props());
87 }
88
89private:
90 SkBitmap fBitmap;
91
92 typedef SkSpecialSurface_Base INHERITED;
93};
94
95sk_sp<SkSpecialSurface> SkSpecialSurface::MakeFromBitmap(const SkIRect& subset, SkBitmap& bm,
96 const SkSurfaceProps* props) {
97 if (subset.isEmpty() || !SkSurfaceValidateRasterInfo(bm.info(), bm.rowBytes())) {
98 return nullptr;
99 }
100 return sk_make_sp<SkSpecialSurface_Raster>(bm.info(), sk_ref_sp(bm.pixelRef()), subset, props);
101}
102
103sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info,
104 const SkSurfaceProps* props) {
105 if (!SkSurfaceValidateRasterInfo(info)) {
106 return nullptr;
107 }
108
109 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0);
110 if (!pr) {
111 return nullptr;
112 }
113
114 const SkIRect subset = SkIRect::MakeWH(info.width(), info.height());
115
116 return sk_make_sp<SkSpecialSurface_Raster>(info, std::move(pr), subset, props);
117}
118
119#if SK_SUPPORT_GPU
120///////////////////////////////////////////////////////////////////////////////
121#include "include/gpu/GrRecordingContext.h"
122#include "src/gpu/GrRecordingContextPriv.h"
123#include "src/gpu/SkGpuDevice.h"
124
125class SkSpecialSurface_Gpu : public SkSpecialSurface_Base {
126public:
127 SkSpecialSurface_Gpu(GrRecordingContext* context,
128 std::unique_ptr<GrRenderTargetContext> renderTargetContext,
129 int width, int height, const SkIRect& subset)
130 : INHERITED(subset, &renderTargetContext->surfaceProps())
131 , fReadView(renderTargetContext->readSurfaceView()) {
132 auto device = SkGpuDevice::Make(context, std::move(renderTargetContext),
133 SkGpuDevice::kUninit_InitContents);
134 if (!device) {
135 return;
136 }
137
138 fCanvas = std::make_unique<SkCanvas>(std::move(device));
139 fCanvas->clipRect(SkRect::Make(subset));
140#ifdef SK_IS_BOT
141 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness
142#endif
143 }
144
145 sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
146 if (!fReadView.asTextureProxy()) {
147 return nullptr;
148 }
149 GrColorType ct = SkColorTypeToGrColorType(fCanvas->imageInfo().colorType());
150
151 // Note: SkSpecialImages can only be snapShotted once, so this call is destructive and we
152 // move fReadMove.
153 return SkSpecialImage::MakeDeferredFromGpu(fCanvas->recordingContext(),
154 this->subset(),
155 kNeedNewImageUniqueID_SpecialImage,
156 std::move(fReadView), ct,
157 fCanvas->imageInfo().refColorSpace(),
158 &this->props());
159 }
160
161private:
162 GrSurfaceProxyView fReadView;
163 typedef SkSpecialSurface_Base INHERITED;
164};
165
166sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRenderTarget(GrRecordingContext* context,
167 int width, int height,
168 GrColorType colorType,
169 sk_sp<SkColorSpace> colorSpace,
170 const SkSurfaceProps* props) {
171 if (!context) {
172 return nullptr;
173 }
174 auto renderTargetContext = GrRenderTargetContext::Make(
175 context, colorType, std::move(colorSpace), SkBackingFit::kApprox, {width, height}, 1,
176 GrMipmapped::kNo, GrProtected::kNo, kBottomLeft_GrSurfaceOrigin, SkBudgeted::kYes,
177 props);
178 if (!renderTargetContext) {
179 return nullptr;
180 }
181
182 const SkIRect subset = SkIRect::MakeWH(width, height);
183
184 return sk_make_sp<SkSpecialSurface_Gpu>(context, std::move(renderTargetContext),
185 width, height, subset);
186}
187
188#endif
189