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 | /////////////////////////////////////////////////////////////////////////////// |
17 | class SkSpecialSurface_Base : public SkSpecialSurface { |
18 | public: |
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 | |
32 | protected: |
33 | std::unique_ptr<SkCanvas> fCanvas; // initialized by derived classes in ctors |
34 | |
35 | private: |
36 | typedef SkSpecialSurface INHERITED; |
37 | }; |
38 | |
39 | /////////////////////////////////////////////////////////////////////////////// |
40 | static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) { |
41 | return static_cast<SkSpecialSurface_Base*>(surface); |
42 | } |
43 | |
44 | SkSpecialSurface::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 | |
52 | SkCanvas* SkSpecialSurface::getCanvas() { |
53 | return as_SB(this)->onGetCanvas(); |
54 | } |
55 | |
56 | sk_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 | |
65 | class SkSpecialSurface_Raster : public SkSpecialSurface_Base { |
66 | public: |
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 | |
89 | private: |
90 | SkBitmap fBitmap; |
91 | |
92 | typedef SkSpecialSurface_Base INHERITED; |
93 | }; |
94 | |
95 | sk_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 | |
103 | sk_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 | |
125 | class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { |
126 | public: |
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 | |
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 | |