xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrOpsRenderPass.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 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 GrOpsRenderPass_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define GrOpsRenderPass_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkDrawable.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBuffer.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDeferredUpload.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrXferProcessor.h"
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker #include <array>
22*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
23*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
24*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker class GrGeometryProcessor;
27*c8dee2aaSAndroid Build Coastguard Worker class GrGpu;
28*c8dee2aaSAndroid Build Coastguard Worker class GrOpFlushState;
29*c8dee2aaSAndroid Build Coastguard Worker class GrPipeline;
30*c8dee2aaSAndroid Build Coastguard Worker class GrProgramInfo;
31*c8dee2aaSAndroid Build Coastguard Worker class GrRenderTarget;
32*c8dee2aaSAndroid Build Coastguard Worker class GrScissorState;
33*c8dee2aaSAndroid Build Coastguard Worker class GrSurfaceProxy;
34*c8dee2aaSAndroid Build Coastguard Worker struct SkIRect;
35*c8dee2aaSAndroid Build Coastguard Worker struct SkRect;
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker /**
38*c8dee2aaSAndroid Build Coastguard Worker  * The GrOpsRenderPass is a series of commands (draws, clears, and discards), which all target the
39*c8dee2aaSAndroid Build Coastguard Worker  * same render target. It is possible that these commands execute immediately (GL), or get buffered
40*c8dee2aaSAndroid Build Coastguard Worker  * up for later execution (Vulkan). GrOps execute into a GrOpsRenderPass.
41*c8dee2aaSAndroid Build Coastguard Worker  */
42*c8dee2aaSAndroid Build Coastguard Worker class GrOpsRenderPass {
43*c8dee2aaSAndroid Build Coastguard Worker public:
~GrOpsRenderPass()44*c8dee2aaSAndroid Build Coastguard Worker     virtual ~GrOpsRenderPass() {}
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker     struct LoadAndStoreInfo {
47*c8dee2aaSAndroid Build Coastguard Worker         GrLoadOp             fLoadOp;
48*c8dee2aaSAndroid Build Coastguard Worker         GrStoreOp            fStoreOp;
49*c8dee2aaSAndroid Build Coastguard Worker         std::array<float, 4> fClearColor;
50*c8dee2aaSAndroid Build Coastguard Worker     };
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     // Load-time clears of the stencil buffer are always to 0 so we don't store
53*c8dee2aaSAndroid Build Coastguard Worker     // an 'fStencilClearValue'
54*c8dee2aaSAndroid Build Coastguard Worker     struct StencilLoadAndStoreInfo {
55*c8dee2aaSAndroid Build Coastguard Worker         GrLoadOp  fLoadOp;
56*c8dee2aaSAndroid Build Coastguard Worker         GrStoreOp fStoreOp;
57*c8dee2aaSAndroid Build Coastguard Worker     };
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker     void begin();
60*c8dee2aaSAndroid Build Coastguard Worker     // Signals the end of recording to the GrOpsRenderPass and that it can now be submitted.
61*c8dee2aaSAndroid Build Coastguard Worker     void end();
62*c8dee2aaSAndroid Build Coastguard Worker 
63*c8dee2aaSAndroid Build Coastguard Worker     // Updates the internal pipeline state for drawing with the provided GrProgramInfo. Enters an
64*c8dee2aaSAndroid Build Coastguard Worker     // internal "bad" state if the pipeline could not be set.
65*c8dee2aaSAndroid Build Coastguard Worker     void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds);
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker     // The scissor rect is always dynamic state and therefore not stored on GrPipeline. If scissor
68*c8dee2aaSAndroid Build Coastguard Worker     // test is enabled on the current pipeline, then the client must call setScissorRect() before
69*c8dee2aaSAndroid Build Coastguard Worker     // drawing. The scissor rect may also be updated between draws without having to bind a new
70*c8dee2aaSAndroid Build Coastguard Worker     // pipeline.
71*c8dee2aaSAndroid Build Coastguard Worker     void setScissorRect(const SkIRect&);
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     // Binds textures for the primitive processor and any FP on the GrPipeline. Texture bindings are
74*c8dee2aaSAndroid Build Coastguard Worker     // dynamic state and therefore not set during bindPipeline(). If the current program uses
75*c8dee2aaSAndroid Build Coastguard Worker     // textures, then the client must call bindTextures() before drawing. The primitive processor
76*c8dee2aaSAndroid Build Coastguard Worker     // textures may also be updated between draws by calling bindTextures() again with a different
77*c8dee2aaSAndroid Build Coastguard Worker     // array for primProcTextures. (On subsequent calls, if the backend is capable of updating the
78*c8dee2aaSAndroid Build Coastguard Worker     // primitive processor textures independently, then it will automatically skip re-binding
79*c8dee2aaSAndroid Build Coastguard Worker     // FP textures from GrPipeline.)
80*c8dee2aaSAndroid Build Coastguard Worker     //
81*c8dee2aaSAndroid Build Coastguard Worker     // If the current program does not use textures, this is a no-op.
82*c8dee2aaSAndroid Build Coastguard Worker     void bindTextures(const GrGeometryProcessor&,
83*c8dee2aaSAndroid Build Coastguard Worker                       const GrSurfaceProxy* const geomProcTextures[],
84*c8dee2aaSAndroid Build Coastguard Worker                       const GrPipeline&);
85*c8dee2aaSAndroid Build Coastguard Worker 
86*c8dee2aaSAndroid Build Coastguard Worker     void bindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer,
87*c8dee2aaSAndroid Build Coastguard Worker                      sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart = GrPrimitiveRestart::kNo);
88*c8dee2aaSAndroid Build Coastguard Worker 
89*c8dee2aaSAndroid Build Coastguard Worker     // The next several draw*() methods issue draws using the current pipeline state. Before
90*c8dee2aaSAndroid Build Coastguard Worker     // drawing, the caller must configure the pipeline and dynamic state:
91*c8dee2aaSAndroid Build Coastguard Worker     //
92*c8dee2aaSAndroid Build Coastguard Worker     //   - Call bindPipeline()
93*c8dee2aaSAndroid Build Coastguard Worker     //   - If the scissor test is enabled, call setScissorRect()
94*c8dee2aaSAndroid Build Coastguard Worker     //   - If the current program uses textures, call bindTextures()
95*c8dee2aaSAndroid Build Coastguard Worker     //   - Call bindBuffers() (even if all buffers are null)
96*c8dee2aaSAndroid Build Coastguard Worker     void draw(int vertexCount, int baseVertex);
97*c8dee2aaSAndroid Build Coastguard Worker     void drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue,
98*c8dee2aaSAndroid Build Coastguard Worker                      int baseVertex);
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker     // Requires caps.drawInstancedSupport().
101*c8dee2aaSAndroid Build Coastguard Worker     void drawInstanced(int instanceCount, int baseInstance, int vertexCount, int baseVertex);
102*c8dee2aaSAndroid Build Coastguard Worker 
103*c8dee2aaSAndroid Build Coastguard Worker     // Requires caps.drawInstancedSupport().
104*c8dee2aaSAndroid Build Coastguard Worker     void drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
105*c8dee2aaSAndroid Build Coastguard Worker                               int baseVertex);
106*c8dee2aaSAndroid Build Coastguard Worker 
107*c8dee2aaSAndroid Build Coastguard Worker     // Executes multiple draws from an array of GrDrawIndirectCommand in the provided buffer.
108*c8dee2aaSAndroid Build Coastguard Worker     //
109*c8dee2aaSAndroid Build Coastguard Worker     // Requires caps.drawInstancedSupport().
110*c8dee2aaSAndroid Build Coastguard Worker     //
111*c8dee2aaSAndroid Build Coastguard Worker     // If caps.nativeDrawIndirectSupport() is unavailable, then 'drawIndirectBuffer' must be a
112*c8dee2aaSAndroid Build Coastguard Worker     // GrCpuBuffer in order to polyfill. Performance may suffer in this scenario.
113*c8dee2aaSAndroid Build Coastguard Worker     void drawIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset, int drawCount);
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker     // Executes multiple draws from an array of GrDrawIndexedIndirectCommand in the provided buffer.
116*c8dee2aaSAndroid Build Coastguard Worker     //
117*c8dee2aaSAndroid Build Coastguard Worker     // Requires caps.drawInstancedSupport().
118*c8dee2aaSAndroid Build Coastguard Worker     //
119*c8dee2aaSAndroid Build Coastguard Worker     // If caps.nativeDrawIndirectSupport() is unavailable, then 'drawIndirectBuffer' must be a
120*c8dee2aaSAndroid Build Coastguard Worker     // GrCpuBuffer in order to polyfill. Performance may suffer in this scenario.
121*c8dee2aaSAndroid Build Coastguard Worker     void drawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset,
122*c8dee2aaSAndroid Build Coastguard Worker                              int drawCount);
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     // This is a helper method for drawing a repeating pattern of vertices. The bound index buffer
125*c8dee2aaSAndroid Build Coastguard Worker     // is understood to contain 'maxPatternRepetitionsInIndexBuffer' repetitions of the pattern.
126*c8dee2aaSAndroid Build Coastguard Worker     // If more repetitions are required, then we loop.
127*c8dee2aaSAndroid Build Coastguard Worker     void drawIndexPattern(int patternIndexCount, int patternRepeatCount,
128*c8dee2aaSAndroid Build Coastguard Worker                           int maxPatternRepetitionsInIndexBuffer, int patternVertexCount,
129*c8dee2aaSAndroid Build Coastguard Worker                           int baseVertex);
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker     // Performs an upload of vertex data in the middle of a set of a set of draws
132*c8dee2aaSAndroid Build Coastguard Worker     virtual void inlineUpload(GrOpFlushState*, GrDeferredTextureUploadFn&) = 0;
133*c8dee2aaSAndroid Build Coastguard Worker 
134*c8dee2aaSAndroid Build Coastguard Worker     /**
135*c8dee2aaSAndroid Build Coastguard Worker      * Clear the owned render target. Clears the full target if 'scissor' is disabled, otherwise it
136*c8dee2aaSAndroid Build Coastguard Worker      * is restricted to 'scissor'. Must check caps.performPartialClearsAsDraws() before using an
137*c8dee2aaSAndroid Build Coastguard Worker      * enabled scissor test; must check caps.performColorClearsAsDraws() before using this at all.
138*c8dee2aaSAndroid Build Coastguard Worker      */
139*c8dee2aaSAndroid Build Coastguard Worker     void clear(const GrScissorState& scissor, std::array<float, 4> color);
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     /**
142*c8dee2aaSAndroid Build Coastguard Worker      * Same as clear() but modifies the stencil; check caps.performStencilClearsAsDraws() and
143*c8dee2aaSAndroid Build Coastguard Worker      * caps.performPartialClearsAsDraws().
144*c8dee2aaSAndroid Build Coastguard Worker      */
145*c8dee2aaSAndroid Build Coastguard Worker     void clearStencilClip(const GrScissorState& scissor, bool insideStencilMask);
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker     /**
148*c8dee2aaSAndroid Build Coastguard Worker      * Executes the SkDrawable object for the underlying backend.
149*c8dee2aaSAndroid Build Coastguard Worker      */
150*c8dee2aaSAndroid Build Coastguard Worker     void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>);
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker protected:
GrOpsRenderPass()153*c8dee2aaSAndroid Build Coastguard Worker     GrOpsRenderPass() : fOrigin(kTopLeft_GrSurfaceOrigin), fRenderTarget(nullptr) {}
154*c8dee2aaSAndroid Build Coastguard Worker 
GrOpsRenderPass(GrRenderTarget * rt,GrSurfaceOrigin origin)155*c8dee2aaSAndroid Build Coastguard Worker     GrOpsRenderPass(GrRenderTarget* rt, GrSurfaceOrigin origin)
156*c8dee2aaSAndroid Build Coastguard Worker             : fOrigin(origin)
157*c8dee2aaSAndroid Build Coastguard Worker             , fRenderTarget(rt) {
158*c8dee2aaSAndroid Build Coastguard Worker     }
159*c8dee2aaSAndroid Build Coastguard Worker 
set(GrRenderTarget * rt,GrSurfaceOrigin origin)160*c8dee2aaSAndroid Build Coastguard Worker     void set(GrRenderTarget* rt, GrSurfaceOrigin origin) {
161*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!fRenderTarget);
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker         fRenderTarget = rt;
164*c8dee2aaSAndroid Build Coastguard Worker         fOrigin = origin;
165*c8dee2aaSAndroid Build Coastguard Worker     }
166*c8dee2aaSAndroid Build Coastguard Worker 
167*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceOrigin fOrigin;
168*c8dee2aaSAndroid Build Coastguard Worker     GrRenderTarget* fRenderTarget;
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker     // Backends may defer binding of certain buffers if their draw API requires a buffer, or if
171*c8dee2aaSAndroid Build Coastguard Worker     // their bind methods don't support base values.
172*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<const GrBuffer> fActiveIndexBuffer;
173*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<const GrBuffer> fActiveVertexBuffer;
174*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<const GrBuffer> fActiveInstanceBuffer;
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker private:
177*c8dee2aaSAndroid Build Coastguard Worker     virtual GrGpu* gpu() = 0;
178*c8dee2aaSAndroid Build Coastguard Worker 
resetActiveBuffers()179*c8dee2aaSAndroid Build Coastguard Worker     void resetActiveBuffers() {
180*c8dee2aaSAndroid Build Coastguard Worker         fActiveIndexBuffer.reset();
181*c8dee2aaSAndroid Build Coastguard Worker         fActiveInstanceBuffer.reset();
182*c8dee2aaSAndroid Build Coastguard Worker         fActiveVertexBuffer.reset();
183*c8dee2aaSAndroid Build Coastguard Worker     }
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker     bool prepareToDraw();
186*c8dee2aaSAndroid Build Coastguard Worker 
187*c8dee2aaSAndroid Build Coastguard Worker     // overridden by backend-specific derived class to perform the rendering command.
onBegin()188*c8dee2aaSAndroid Build Coastguard Worker     virtual void onBegin() {}
onEnd()189*c8dee2aaSAndroid Build Coastguard Worker     virtual void onEnd() {}
190*c8dee2aaSAndroid Build Coastguard Worker     virtual bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) = 0;
191*c8dee2aaSAndroid Build Coastguard Worker     virtual void onSetScissorRect(const SkIRect&) = 0;
192*c8dee2aaSAndroid Build Coastguard Worker     virtual bool onBindTextures(const GrGeometryProcessor&,
193*c8dee2aaSAndroid Build Coastguard Worker                                 const GrSurfaceProxy* const geomProcTextures[],
194*c8dee2aaSAndroid Build Coastguard Worker                                 const GrPipeline&) = 0;
195*c8dee2aaSAndroid Build Coastguard Worker     virtual void onBindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer,
196*c8dee2aaSAndroid Build Coastguard Worker                                sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart) = 0;
197*c8dee2aaSAndroid Build Coastguard Worker     virtual void onDraw(int vertexCount, int baseVertex) = 0;
198*c8dee2aaSAndroid Build Coastguard Worker     virtual void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
199*c8dee2aaSAndroid Build Coastguard Worker                                uint16_t maxIndexValue, int baseVertex) = 0;
200*c8dee2aaSAndroid Build Coastguard Worker     virtual void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
201*c8dee2aaSAndroid Build Coastguard Worker                                  int baseVertex) = 0;
202*c8dee2aaSAndroid Build Coastguard Worker     virtual void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
203*c8dee2aaSAndroid Build Coastguard Worker                                         int baseInstance, int baseVertex) = 0;
onDrawIndirect(const GrBuffer *,size_t offset,int drawCount)204*c8dee2aaSAndroid Build Coastguard Worker     virtual void onDrawIndirect(const GrBuffer*, size_t offset, int drawCount) {
205*c8dee2aaSAndroid Build Coastguard Worker         SK_ABORT("Not implemented.");  // Only called if caps.nativeDrawIndirectSupport().
206*c8dee2aaSAndroid Build Coastguard Worker     }
onDrawIndexedIndirect(const GrBuffer *,size_t offset,int drawCount)207*c8dee2aaSAndroid Build Coastguard Worker     virtual void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) {
208*c8dee2aaSAndroid Build Coastguard Worker         SK_ABORT("Not implemented.");  // Only called if caps.nativeDrawIndirectSupport().
209*c8dee2aaSAndroid Build Coastguard Worker     }
210*c8dee2aaSAndroid Build Coastguard Worker     virtual void onClear(const GrScissorState&, std::array<float, 4> color) = 0;
211*c8dee2aaSAndroid Build Coastguard Worker     virtual void onClearStencilClip(const GrScissorState&, bool insideStencilMask) = 0;
onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>)212*c8dee2aaSAndroid Build Coastguard Worker     virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {}
213*c8dee2aaSAndroid Build Coastguard Worker 
214*c8dee2aaSAndroid Build Coastguard Worker     enum class DrawPipelineStatus {
215*c8dee2aaSAndroid Build Coastguard Worker         kOk = 0,
216*c8dee2aaSAndroid Build Coastguard Worker         kNotConfigured,
217*c8dee2aaSAndroid Build Coastguard Worker         kFailedToBind
218*c8dee2aaSAndroid Build Coastguard Worker     };
219*c8dee2aaSAndroid Build Coastguard Worker 
220*c8dee2aaSAndroid Build Coastguard Worker     DrawPipelineStatus fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
221*c8dee2aaSAndroid Build Coastguard Worker     GrXferBarrierType fXferBarrierType;
222*c8dee2aaSAndroid Build Coastguard Worker 
223*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
224*c8dee2aaSAndroid Build Coastguard Worker     enum class DynamicStateStatus {
225*c8dee2aaSAndroid Build Coastguard Worker         kDisabled,
226*c8dee2aaSAndroid Build Coastguard Worker         kUninitialized,
227*c8dee2aaSAndroid Build Coastguard Worker         kConfigured
228*c8dee2aaSAndroid Build Coastguard Worker     };
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker     DynamicStateStatus fScissorStatus;
231*c8dee2aaSAndroid Build Coastguard Worker     DynamicStateStatus fTextureBindingStatus;
232*c8dee2aaSAndroid Build Coastguard Worker     bool fHasIndexBuffer;
233*c8dee2aaSAndroid Build Coastguard Worker     DynamicStateStatus fInstanceBufferStatus;
234*c8dee2aaSAndroid Build Coastguard Worker     DynamicStateStatus fVertexBufferStatus;
235*c8dee2aaSAndroid Build Coastguard Worker #endif
236*c8dee2aaSAndroid Build Coastguard Worker 
237*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = GrOpsRenderPass;
238*c8dee2aaSAndroid Build Coastguard Worker };
239*c8dee2aaSAndroid Build Coastguard Worker 
240*c8dee2aaSAndroid Build Coastguard Worker #endif
241