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 "include/core/SkCanvas.h" |
9 | #include "src/core/SkSpecialImage.h" |
10 | #include "src/core/SkSpecialSurface.h" |
11 | #include "src/core/SkSurfacePriv.h" |
12 | |
13 | /////////////////////////////////////////////////////////////////////////////// |
14 | class SkSpecialSurface_Base : public SkSpecialSurface { |
15 | public: |
16 | SkSpecialSurface_Base(const SkIRect& subset, const SkSurfaceProps* props) |
17 | : INHERITED(subset, props) |
18 | , fCanvas(nullptr) { |
19 | } |
20 | |
21 | virtual ~SkSpecialSurface_Base() { } |
22 | |
23 | // reset is called after an SkSpecialImage has been snapped |
24 | void reset() { fCanvas.reset(); } |
25 | |
26 | // This can return nullptr if reset has already been called or something when wrong in the ctor |
27 | SkCanvas* onGetCanvas() { return fCanvas.get(); } |
28 | |
29 | virtual sk_sp<SkSpecialImage> onMakeImageSnapshot() = 0; |
30 | |
31 | protected: |
32 | std::unique_ptr<SkCanvas> fCanvas; // initialized by derived classes in ctors |
33 | |
34 | private: |
35 | typedef SkSpecialSurface INHERITED; |
36 | }; |
37 | |
38 | /////////////////////////////////////////////////////////////////////////////// |
39 | static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) { |
40 | return static_cast<SkSpecialSurface_Base*>(surface); |
41 | } |
42 | |
43 | SkSpecialSurface::SkSpecialSurface(const SkIRect& subset, |
44 | const SkSurfaceProps* props) |
45 | : fProps(SkSurfacePropsCopyOrDefault(props).flags(), kUnknown_SkPixelGeometry) |
46 | , fSubset(subset) { |
47 | SkASSERT(fSubset.width() > 0); |
48 | SkASSERT(fSubset.height() > 0); |
49 | } |
50 | |
51 | SkCanvas* SkSpecialSurface::getCanvas() { |
52 | return as_SB(this)->onGetCanvas(); |
53 | } |
54 | |
55 | sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() { |
56 | sk_sp<SkSpecialImage> image(as_SB(this)->onMakeImageSnapshot()); |
57 | as_SB(this)->reset(); |
58 | return image; // the caller gets the creation ref |
59 | } |
60 | |
61 | /////////////////////////////////////////////////////////////////////////////// |
62 | #include "include/core/SkMallocPixelRef.h" |
63 | |
64 | class SkSpecialSurface_Raster : public SkSpecialSurface_Base { |
65 | public: |
66 | SkSpecialSurface_Raster(const SkImageInfo& info, |
67 | sk_sp<SkPixelRef> pr, |
68 | const SkIRect& subset, |
69 | const SkSurfaceProps* props) |
70 | : INHERITED(subset, props) { |
71 | SkASSERT(info.width() == pr->width() && info.height() == pr->height()); |
72 | fBitmap.setInfo(info, info.minRowBytes()); |
73 | fBitmap.setPixelRef(std::move(pr), 0, 0); |
74 | |
75 | fCanvas.reset(new SkCanvas(fBitmap, this->props())); |
76 | fCanvas->clipRect(SkRect::Make(subset)); |
77 | #ifdef SK_IS_BOT |
78 | fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness |
79 | #endif |
80 | } |
81 | |
82 | ~SkSpecialSurface_Raster() override { } |
83 | |
84 | sk_sp<SkSpecialImage> onMakeImageSnapshot() override { |
85 | return SkSpecialImage::MakeFromRaster(this->subset(), fBitmap, &this->props()); |
86 | } |
87 | |
88 | private: |
89 | SkBitmap fBitmap; |
90 | |
91 | typedef SkSpecialSurface_Base INHERITED; |
92 | }; |
93 | |
94 | sk_sp<SkSpecialSurface> SkSpecialSurface::MakeFromBitmap(const SkIRect& subset, SkBitmap& bm, |
95 | const SkSurfaceProps* props) { |
96 | if (subset.isEmpty() || !SkSurfaceValidateRasterInfo(bm.info(), bm.rowBytes())) { |
97 | return nullptr; |
98 | } |
99 | return sk_make_sp<SkSpecialSurface_Raster>(bm.info(), sk_ref_sp(bm.pixelRef()), subset, props); |
100 | } |
101 | |
102 | sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info, |
103 | const SkSurfaceProps* props) { |
104 | if (!SkSurfaceValidateRasterInfo(info)) { |
105 | return nullptr; |
106 | } |
107 | |
108 | sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0); |
109 | if (!pr) { |
110 | return nullptr; |
111 | } |
112 | |
113 | const SkIRect subset = SkIRect::MakeWH(info.width(), info.height()); |
114 | |
115 | return sk_make_sp<SkSpecialSurface_Raster>(info, std::move(pr), subset, props); |
116 | } |
117 | |
118 | #if SK_SUPPORT_GPU |
119 | /////////////////////////////////////////////////////////////////////////////// |
120 | #include "include/private/GrRecordingContext.h" |
121 | #include "src/gpu/GrRecordingContextPriv.h" |
122 | #include "src/gpu/SkGpuDevice.h" |
123 | |
124 | class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { |
125 | public: |
126 | SkSpecialSurface_Gpu(GrRecordingContext* context, |
127 | std::unique_ptr<GrRenderTargetContext> renderTargetContext, |
128 | int width, int height, const SkIRect& subset) |
129 | : INHERITED(subset, &renderTargetContext->surfaceProps()) |
130 | , fReadView(renderTargetContext->readSurfaceView()) { |
131 | // CONTEXT TODO: remove this use of 'backdoor' to create an SkGpuDevice |
132 | auto device = SkGpuDevice::Make(context->priv().backdoor(), std::move(renderTargetContext), |
133 | SkGpuDevice::kUninit_InitContents); |
134 | if (!device) { |
135 | return; |
136 | } |
137 | |
138 | fCanvas.reset(new 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->getGrContext(), |
154 | this->subset(), |
155 | kNeedNewImageUniqueID_SpecialImage, |
156 | std::move(fReadView), ct, |
157 | fCanvas->imageInfo().refColorSpace(), |
158 | &this->props()); |
159 | } |
160 | |
161 | private: |
162 | GrSurfaceProxyView fReadView; |
163 | typedef SkSpecialSurface_Base INHERITED; |
164 | }; |
165 | |
166 | sk_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 | |