1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkSurface_Base_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkSurface_Base_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
20*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Worker class GrBackendSemaphore;
23*c8dee2aaSAndroid Build Coastguard Worker class GrBackendTexture;
24*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
25*c8dee2aaSAndroid Build Coastguard Worker class SkCapabilities;
26*c8dee2aaSAndroid Build Coastguard Worker class SkColorSpace;
27*c8dee2aaSAndroid Build Coastguard Worker class SkPaint;
28*c8dee2aaSAndroid Build Coastguard Worker class SkPixmap;
29*c8dee2aaSAndroid Build Coastguard Worker class GrSurfaceCharacterization;
30*c8dee2aaSAndroid Build Coastguard Worker class SkSurfaceProps;
31*c8dee2aaSAndroid Build Coastguard Worker enum GrSurfaceOrigin : int;
32*c8dee2aaSAndroid Build Coastguard Worker enum SkYUVColorSpace : int;
33*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu { namespace graphite { class Recorder; } }
34*c8dee2aaSAndroid Build Coastguard Worker struct SkIRect;
35*c8dee2aaSAndroid Build Coastguard Worker struct SkISize;
36*c8dee2aaSAndroid Build Coastguard Worker struct SkImageInfo;
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker class SkSurface_Base : public SkSurface {
39*c8dee2aaSAndroid Build Coastguard Worker public:
40*c8dee2aaSAndroid Build Coastguard Worker SkSurface_Base(int width, int height, const SkSurfaceProps*);
41*c8dee2aaSAndroid Build Coastguard Worker SkSurface_Base(const SkImageInfo&, const SkSurfaceProps*);
42*c8dee2aaSAndroid Build Coastguard Worker ~SkSurface_Base() override;
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker // From SkSurface.h
replaceBackendTexture(const GrBackendTexture &,GrSurfaceOrigin,ContentChangeMode,TextureReleaseProc,ReleaseContext)45*c8dee2aaSAndroid Build Coastguard Worker bool replaceBackendTexture(const GrBackendTexture&,
46*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin,
47*c8dee2aaSAndroid Build Coastguard Worker ContentChangeMode,
48*c8dee2aaSAndroid Build Coastguard Worker TextureReleaseProc,
49*c8dee2aaSAndroid Build Coastguard Worker ReleaseContext) override {
50*c8dee2aaSAndroid Build Coastguard Worker return false;
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker enum class Type {
54*c8dee2aaSAndroid Build Coastguard Worker kNull, // intentionally associating 0 with a null canvas
55*c8dee2aaSAndroid Build Coastguard Worker kGanesh,
56*c8dee2aaSAndroid Build Coastguard Worker kGraphite,
57*c8dee2aaSAndroid Build Coastguard Worker kRaster,
58*c8dee2aaSAndroid Build Coastguard Worker };
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker // TODO(kjlubick) Android directly subclasses SkSurface_Base for tests, so we
61*c8dee2aaSAndroid Build Coastguard Worker // cannot make this a pure virtual. They seem to want a surface that is spy-able
62*c8dee2aaSAndroid Build Coastguard Worker // or mockable, so maybe we should provide something like that.
type()63*c8dee2aaSAndroid Build Coastguard Worker virtual Type type() const { return Type::kNull; }
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker // True for surfaces instantiated by pixels in CPU memory
isRasterBacked()66*c8dee2aaSAndroid Build Coastguard Worker bool isRasterBacked() const { return this->type() == Type::kRaster; }
67*c8dee2aaSAndroid Build Coastguard Worker // True for surfaces instantiated by Ganesh in GPU memory
isGaneshBacked()68*c8dee2aaSAndroid Build Coastguard Worker bool isGaneshBacked() const { return this->type() == Type::kGanesh; }
69*c8dee2aaSAndroid Build Coastguard Worker // True for surfaces instantiated by Graphite in GPU memory
isGraphiteBacked()70*c8dee2aaSAndroid Build Coastguard Worker bool isGraphiteBacked() const { return this->type() == Type::kGraphite; }
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker virtual GrRecordingContext* onGetRecordingContext() const;
73*c8dee2aaSAndroid Build Coastguard Worker virtual skgpu::graphite::Recorder* onGetRecorder() const;
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker /**
76*c8dee2aaSAndroid Build Coastguard Worker * Allocate a canvas that will draw into this surface. We will cache this
77*c8dee2aaSAndroid Build Coastguard Worker * canvas, to return the same object to the caller multiple times. We
78*c8dee2aaSAndroid Build Coastguard Worker * take ownership, and will call unref() on the canvas when we go out of
79*c8dee2aaSAndroid Build Coastguard Worker * scope.
80*c8dee2aaSAndroid Build Coastguard Worker */
81*c8dee2aaSAndroid Build Coastguard Worker virtual SkCanvas* onNewCanvas() = 0;
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&) = 0;
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker /**
86*c8dee2aaSAndroid Build Coastguard Worker * Allocate an SkImage that represents the current contents of the surface.
87*c8dee2aaSAndroid Build Coastguard Worker * This needs to be able to outlive the surface itself (if need be), and
88*c8dee2aaSAndroid Build Coastguard Worker * must faithfully represent the current contents, even if the surface
89*c8dee2aaSAndroid Build Coastguard Worker * is changed after this called (e.g. it is drawn to via its canvas).
90*c8dee2aaSAndroid Build Coastguard Worker *
91*c8dee2aaSAndroid Build Coastguard Worker * If a subset is specified, the the impl must make a copy, rather than try to wait
92*c8dee2aaSAndroid Build Coastguard Worker * on copy-on-write.
93*c8dee2aaSAndroid Build Coastguard Worker */
94*c8dee2aaSAndroid Build Coastguard Worker virtual sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset = nullptr) { return nullptr; }
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker virtual void onWritePixels(const SkPixmap&, int x, int y) = 0;
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker /**
99*c8dee2aaSAndroid Build Coastguard Worker * Default implementation does a rescale/read and then calls the callback.
100*c8dee2aaSAndroid Build Coastguard Worker */
101*c8dee2aaSAndroid Build Coastguard Worker virtual void onAsyncRescaleAndReadPixels(const SkImageInfo&,
102*c8dee2aaSAndroid Build Coastguard Worker const SkIRect srcRect,
103*c8dee2aaSAndroid Build Coastguard Worker RescaleGamma,
104*c8dee2aaSAndroid Build Coastguard Worker RescaleMode,
105*c8dee2aaSAndroid Build Coastguard Worker ReadPixelsCallback,
106*c8dee2aaSAndroid Build Coastguard Worker ReadPixelsContext);
107*c8dee2aaSAndroid Build Coastguard Worker /**
108*c8dee2aaSAndroid Build Coastguard Worker * Default implementation does a rescale/read/yuv conversion and then calls the callback.
109*c8dee2aaSAndroid Build Coastguard Worker */
110*c8dee2aaSAndroid Build Coastguard Worker virtual void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace,
111*c8dee2aaSAndroid Build Coastguard Worker bool readAlpha,
112*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> dstColorSpace,
113*c8dee2aaSAndroid Build Coastguard Worker SkIRect srcRect,
114*c8dee2aaSAndroid Build Coastguard Worker SkISize dstSize,
115*c8dee2aaSAndroid Build Coastguard Worker RescaleGamma,
116*c8dee2aaSAndroid Build Coastguard Worker RescaleMode,
117*c8dee2aaSAndroid Build Coastguard Worker ReadPixelsCallback,
118*c8dee2aaSAndroid Build Coastguard Worker ReadPixelsContext);
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker /**
121*c8dee2aaSAndroid Build Coastguard Worker * Default implementation:
122*c8dee2aaSAndroid Build Coastguard Worker *
123*c8dee2aaSAndroid Build Coastguard Worker * image = this->newImageSnapshot();
124*c8dee2aaSAndroid Build Coastguard Worker * if (image) {
125*c8dee2aaSAndroid Build Coastguard Worker * image->draw(canvas, ...);
126*c8dee2aaSAndroid Build Coastguard Worker * image->unref();
127*c8dee2aaSAndroid Build Coastguard Worker * }
128*c8dee2aaSAndroid Build Coastguard Worker */
129*c8dee2aaSAndroid Build Coastguard Worker virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkSamplingOptions&,const SkPaint*);
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker /**
132*c8dee2aaSAndroid Build Coastguard Worker * Called as a performance hint when the Surface is allowed to make it's contents
133*c8dee2aaSAndroid Build Coastguard Worker * undefined.
134*c8dee2aaSAndroid Build Coastguard Worker */
onDiscard()135*c8dee2aaSAndroid Build Coastguard Worker virtual void onDiscard() {}
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker /**
138*c8dee2aaSAndroid Build Coastguard Worker * If the surface is about to change, we call this so that our subclass
139*c8dee2aaSAndroid Build Coastguard Worker * can optionally fork their backend (copy-on-write) in case it was
140*c8dee2aaSAndroid Build Coastguard Worker * being shared with the cachedImage.
141*c8dee2aaSAndroid Build Coastguard Worker *
142*c8dee2aaSAndroid Build Coastguard Worker * Returns false if the backing cannot be un-shared.
143*c8dee2aaSAndroid Build Coastguard Worker */
144*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] virtual bool onCopyOnWrite(ContentChangeMode) = 0;
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker /**
147*c8dee2aaSAndroid Build Coastguard Worker * Signal the surface to remind its backing store that it's mutable again.
148*c8dee2aaSAndroid Build Coastguard Worker * Called only when we _didn't_ copy-on-write; we assume the copies start mutable.
149*c8dee2aaSAndroid Build Coastguard Worker */
onRestoreBackingMutability()150*c8dee2aaSAndroid Build Coastguard Worker virtual void onRestoreBackingMutability() {}
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker /**
153*c8dee2aaSAndroid Build Coastguard Worker * Caused the current backend 3D API to wait on the passed in semaphores before executing new
154*c8dee2aaSAndroid Build Coastguard Worker * commands on the gpu. Any previously submitting commands will not be blocked by these
155*c8dee2aaSAndroid Build Coastguard Worker * semaphores.
156*c8dee2aaSAndroid Build Coastguard Worker */
onWait(int numSemaphores,const GrBackendSemaphore * waitSemaphores,bool deleteSemaphoresAfterWait)157*c8dee2aaSAndroid Build Coastguard Worker virtual bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
158*c8dee2aaSAndroid Build Coastguard Worker bool deleteSemaphoresAfterWait) {
159*c8dee2aaSAndroid Build Coastguard Worker return false;
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker
onCharacterize(GrSurfaceCharacterization *)162*c8dee2aaSAndroid Build Coastguard Worker virtual bool onCharacterize(GrSurfaceCharacterization*) const { return false; }
onIsCompatible(const GrSurfaceCharacterization &)163*c8dee2aaSAndroid Build Coastguard Worker virtual bool onIsCompatible(const GrSurfaceCharacterization&) const { return false; }
164*c8dee2aaSAndroid Build Coastguard Worker
165*c8dee2aaSAndroid Build Coastguard Worker // TODO: Remove this (make it pure virtual) after updating Android (which has a class derived
166*c8dee2aaSAndroid Build Coastguard Worker // from SkSurface_Base).
167*c8dee2aaSAndroid Build Coastguard Worker virtual sk_sp<const SkCapabilities> onCapabilities();
168*c8dee2aaSAndroid Build Coastguard Worker
169*c8dee2aaSAndroid Build Coastguard Worker inline SkCanvas* getCachedCanvas();
170*c8dee2aaSAndroid Build Coastguard Worker inline sk_sp<SkImage> refCachedImage();
171*c8dee2aaSAndroid Build Coastguard Worker
hasCachedImage()172*c8dee2aaSAndroid Build Coastguard Worker bool hasCachedImage() const { return fCachedImage != nullptr; }
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker // called by SkSurface to compute a new genID
175*c8dee2aaSAndroid Build Coastguard Worker uint32_t newGenerationID();
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker private:
178*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCanvas> fCachedCanvas = nullptr;
179*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fCachedImage = nullptr;
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker // Returns false if drawing should not take place (allocation failure).
182*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] bool aboutToDraw(ContentChangeMode mode);
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker // Returns true if there is an outstanding image-snapshot, indicating that a call to aboutToDraw
185*c8dee2aaSAndroid Build Coastguard Worker // would trigger a copy-on-write.
186*c8dee2aaSAndroid Build Coastguard Worker bool outstandingImageSnapshot() const;
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker friend class SkCanvas;
189*c8dee2aaSAndroid Build Coastguard Worker friend class SkSurface;
190*c8dee2aaSAndroid Build Coastguard Worker };
191*c8dee2aaSAndroid Build Coastguard Worker
getCachedCanvas()192*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* SkSurface_Base::getCachedCanvas() {
193*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == fCachedCanvas) {
194*c8dee2aaSAndroid Build Coastguard Worker fCachedCanvas = std::unique_ptr<SkCanvas>(this->onNewCanvas());
195*c8dee2aaSAndroid Build Coastguard Worker if (fCachedCanvas) {
196*c8dee2aaSAndroid Build Coastguard Worker fCachedCanvas->setSurfaceBase(this);
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker }
199*c8dee2aaSAndroid Build Coastguard Worker return fCachedCanvas.get();
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker
refCachedImage()202*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkSurface_Base::refCachedImage() {
203*c8dee2aaSAndroid Build Coastguard Worker if (fCachedImage) {
204*c8dee2aaSAndroid Build Coastguard Worker return fCachedImage;
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker fCachedImage = this->onNewImageSnapshot();
208*c8dee2aaSAndroid Build Coastguard Worker
209*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
210*c8dee2aaSAndroid Build Coastguard Worker return fCachedImage;
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker
asSB(SkSurface * surface)213*c8dee2aaSAndroid Build Coastguard Worker static inline SkSurface_Base* asSB(SkSurface* surface) {
214*c8dee2aaSAndroid Build Coastguard Worker return static_cast<SkSurface_Base*>(surface);
215*c8dee2aaSAndroid Build Coastguard Worker }
216*c8dee2aaSAndroid Build Coastguard Worker
asConstSB(const SkSurface * surface)217*c8dee2aaSAndroid Build Coastguard Worker static inline const SkSurface_Base* asConstSB(const SkSurface* surface) {
218*c8dee2aaSAndroid Build Coastguard Worker return static_cast<const SkSurface_Base*>(surface);
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker #endif
222