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 "include/core/SkColorSpace.h"
14 #include "include/core/SkMallocPixelRef.h"
15 #include "src/core/SkBitmapDevice.h"
16 #include "src/core/SkCanvasPriv.h"
17 #include "src/core/SkDevice.h"
18 #include "src/core/SkSpecialImage.h"
19 #include "src/core/SkSurfacePriv.h"
20
SkSpecialSurface(sk_sp<SkBaseDevice> device,const SkIRect & subset)21 SkSpecialSurface::SkSpecialSurface(sk_sp<SkBaseDevice> device, const SkIRect& subset)
22 : fSubset(subset) {
23 SkASSERT(fSubset.width() > 0);
24 SkASSERT(fSubset.height() > 0);
25
26 fCanvas = std::make_unique<SkCanvas>(std::move(device));
27 fCanvas->clipRect(SkRect::Make(subset));
28 #ifdef SK_IS_BOT
29 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness
30 #endif
31 }
32
makeImageSnapshot()33 sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() {
34 fCanvas->restoreToCount(0);
35
36 // Because of the above 'restoreToCount(0)' we know we're getting the base device here.
37 SkBaseDevice* baseDevice = SkCanvasPriv::TopDevice(fCanvas.get());
38 if (!baseDevice) {
39 return nullptr;
40 }
41
42 sk_sp<SkSpecialImage> image = baseDevice->snapSpecial(this->subset());
43
44 fCanvas.reset();
45 return image;
46 }
47
48 ///////////////////////////////////////////////////////////////////////////////
MakeRaster(const SkImageInfo & info,const SkSurfaceProps & props)49 sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info,
50 const SkSurfaceProps& props) {
51 if (!SkSurfaceValidateRasterInfo(info)) {
52 return nullptr;
53 }
54
55 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0);
56 if (!pr) {
57 return nullptr;
58 }
59
60 SkBitmap bitmap;
61 bitmap.setInfo(info, info.minRowBytes());
62 bitmap.setPixelRef(std::move(pr), 0, 0);
63
64 sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap,
65 { props.flags(), kUnknown_SkPixelGeometry }));
66 if (!device) {
67 return nullptr;
68 }
69
70 const SkIRect subset = SkIRect::MakeSize(info.dimensions());
71
72 return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////
76 #if defined(SK_GANESH)
77 #include "include/gpu/GrRecordingContext.h"
78 #include "src/gpu/SkBackingFit.h"
79 #include "src/gpu/ganesh/GrColorInfo.h"
80 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
81
MakeRenderTarget(GrRecordingContext * rContext,const SkImageInfo & ii,const SkSurfaceProps & props,GrSurfaceOrigin surfaceOrigin)82 sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRenderTarget(GrRecordingContext* rContext,
83 const SkImageInfo& ii,
84 const SkSurfaceProps& props,
85 GrSurfaceOrigin surfaceOrigin) {
86 if (!rContext) {
87 return nullptr;
88 }
89
90 auto device = rContext->priv().createDevice(skgpu::Budgeted::kYes,
91 ii,
92 SkBackingFit::kApprox,
93 1,
94 GrMipmapped::kNo,
95 GrProtected::kNo,
96 surfaceOrigin,
97 {props.flags(), kUnknown_SkPixelGeometry},
98 skgpu::v1::Device::InitContents::kUninit);
99 if (!device) {
100 return nullptr;
101 }
102
103 const SkIRect subset = SkIRect::MakeSize(ii.dimensions());
104
105 return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
106 }
107
108 #endif // defined(SK_GANESH)
109
110 ///////////////////////////////////////////////////////////////////////////////
111 #if SK_GRAPHITE
112 #include "src/gpu/graphite/Device.h"
113
MakeGraphite(skgpu::graphite::Recorder * recorder,const SkImageInfo & ii,const SkSurfaceProps & props)114 sk_sp<SkSpecialSurface> SkSpecialSurface::MakeGraphite(skgpu::graphite::Recorder* recorder,
115 const SkImageInfo& ii,
116 const SkSurfaceProps& props) {
117 using namespace skgpu::graphite;
118
119 if (!recorder) {
120 return nullptr;
121 }
122
123 sk_sp<Device> device = Device::Make(recorder,
124 ii,
125 skgpu::Budgeted::kYes,
126 skgpu::Mipmapped::kNo,
127 {props.flags(), kUnknown_SkPixelGeometry},
128 /* addInitialClear= */ false);
129 if (!device) {
130 return nullptr;
131 }
132
133 const SkIRect subset = SkIRect::MakeSize(ii.dimensions());
134
135 return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
136 }
137
138 #endif // SK_GRAPHITE
139