1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SF_RENDERENGINE_H_
18 #define SF_RENDERENGINE_H_
19 
20 #include <android-base/unique_fd.h>
21 #include <ftl/future.h>
22 #include <math/mat4.h>
23 #include <renderengine/DisplaySettings.h>
24 #include <renderengine/ExternalTexture.h>
25 #include <renderengine/LayerSettings.h>
26 #include <stdint.h>
27 #include <sys/types.h>
28 #include <ui/FenceResult.h>
29 #include <ui/GraphicTypes.h>
30 #include <ui/Transform.h>
31 
32 #include <future>
33 #include <memory>
34 
35 /**
36  * Allows to override the RenderEngine backend.
37  */
38 #define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
39 
40 /**
41  * Turns on recording of skia commands in SkiaGL version of the RE. This property
42  * defines number of milliseconds for the recording to take place. A non zero value
43  * turns on the recording.
44  */
45 #define PROPERTY_DEBUG_RENDERENGINE_CAPTURE_SKIA_MS "debug.renderengine.capture_skia_ms"
46 
47 /**
48  * Set to the most recently saved file once the capture is finished.
49  */
50 #define PROPERTY_DEBUG_RENDERENGINE_CAPTURE_FILENAME "debug.renderengine.capture_filename"
51 
52 /**
53  * Switches the cross-window background blur algorithm.
54  */
55 #define PROPERTY_DEBUG_RENDERENGINE_BLUR_ALGORITHM "debug.renderengine.blur_algorithm"
56 
57 /**
58  * Allows recording of Skia drawing commands with systrace.
59  */
60 #define PROPERTY_SKIA_ATRACE_ENABLED "debug.renderengine.skia_atrace_enabled"
61 
62 struct ANativeWindowBuffer;
63 
64 namespace android {
65 
66 class Rect;
67 class Region;
68 
69 namespace renderengine {
70 
71 class ExternalTexture;
72 class Image;
73 class Mesh;
74 class Texture;
75 struct RenderEngineCreationArgs;
76 
77 namespace threaded {
78 class RenderEngineThreaded;
79 }
80 
81 namespace impl {
82 class RenderEngine;
83 class ExternalTexture;
84 }
85 
86 enum class Protection {
87     UNPROTECTED = 1,
88     PROTECTED = 2,
89 };
90 
91 // Toggles for skipping or enabling priming of particular shaders.
92 struct PrimeCacheConfig {
93     bool cacheHolePunchLayer = true;
94     bool cacheSolidLayers = true;
95     bool cacheSolidDimmedLayers = true;
96     bool cacheImageLayers = true;
97     bool cacheImageDimmedLayers = true;
98     bool cacheClippedLayers = true;
99     bool cacheShadowLayers = true;
100     bool cachePIPImageLayers = true;
101     bool cacheTransparentImageDimmedLayers = true;
102     bool cacheClippedDimmedImageLayers = true;
103     bool cacheUltraHDR = true;
104 };
105 
106 class RenderEngine {
107 public:
108     enum class ContextPriority {
109         LOW = 1,
110         MEDIUM = 2,
111         HIGH = 3,
112         REALTIME = 4,
113     };
114 
115     enum class Threaded {
116         NO,
117         YES,
118     };
119 
120     enum class GraphicsApi {
121         GL,
122         VK,
123     };
124 
125     enum class SkiaBackend {
126         GANESH,
127         GRAPHITE,
128     };
129 
130     enum class BlurAlgorithm {
131         NONE,
132         GAUSSIAN,
133         KAWASE,
134     };
135 
136     static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args);
137 
138     // Check if the device supports the given GraphicsApi.
139     //
140     // If called for GraphicsApi::VK then underlying (unprotected) VK resources will be preserved
141     // to optimize subsequent VK initialization, but teardown(GraphicsApi::VK) must be invoked if
142     // the caller subsequently decides to NOT use VK.
143     //
144     // The first call may require significant resource initialization, but subsequent checks are
145     // cached internally.
146     static bool canSupport(GraphicsApi graphicsApi);
147 
148     // Teardown any GPU API resources that were previously initialized but are no longer needed.
149     //
150     // Must be called with GraphicsApi::VK if canSupport(GraphicsApi::VK) was previously invoked but
151     // the caller subsequently decided to not use VK.
152     //
153     // This is safe to call if there is nothing to teardown, but NOT safe to call if a RenderEngine
154     // instance exists. The RenderEngine destructor will handle its own teardown logic.
155     static void teardown(GraphicsApi graphicsApi);
156 
157     virtual ~RenderEngine() = 0;
158 
159     // ----- BEGIN DEPRECATED INTERFACE -----
160     // This interface, while still in use until a suitable replacement is built,
161     // should be considered deprecated, minus some methods which still may be
162     // used to support legacy behavior.
163     virtual std::future<void> primeCache(PrimeCacheConfig config) = 0;
164 
165     // dump the extension strings. always call the base class.
166     virtual void dump(std::string& result) = 0;
167 
168     // queries that are required to be thread safe
169     virtual size_t getMaxTextureSize() const = 0;
170     virtual size_t getMaxViewportDims() const = 0;
171 
172     // ----- END DEPRECATED INTERFACE -----
173 
174     // ----- BEGIN NEW INTERFACE -----
175 
176     // queries that are required to be thread safe
177     virtual bool supportsProtectedContent() const = 0;
178 
179     // Notify RenderEngine of changes to the dimensions of the active display
180     // so that it can configure its internal caches accordingly.
181     virtual void onActiveDisplaySizeChanged(ui::Size size) = 0;
182 
183     // Renders layers for a particular display via GPU composition. This method
184     // should be called for every display that needs to be rendered via the GPU.
185     // @param display The display-wide settings that should be applied prior to
186     // drawing any layers.
187     //
188     // Assumptions when calling this method:
189     // 1. There is exactly one caller - i.e. multi-threading is not supported.
190     // 2. Additional threads may be calling the {bind,cache}ExternalTexture
191     // methods above. But the main thread is responsible for holding resources
192     // such that Image destruction does not occur while this method is called.
193     //
194     // TODO(b/136806342): This should behavior should ideally be fixed since
195     // the above two assumptions are brittle, as conditional thread safetyness
196     // may be insufficient when maximizing rendering performance in the future.
197     //
198     // @param layers The layers to draw onto the display, in Z-order.
199     // @param buffer The buffer which will be drawn to. This buffer will be
200     // ready once drawFence fires.
201     // @param bufferFence Fence signalling that the buffer is ready to be drawn
202     // to.
203     // @return A future object of FenceResult indicating whether drawing was
204     // successful in async mode.
205     virtual ftl::Future<FenceResult> drawLayers(const DisplaySettings& display,
206                                                 const std::vector<LayerSettings>& layers,
207                                                 const std::shared_ptr<ExternalTexture>& buffer,
208                                                 base::unique_fd&& bufferFence);
209 
210     // Clean-up method that should be called on the main thread after the
211     // drawFence returned by drawLayers fires. This method will free up
212     // resources used by the most recently drawn frame. If the frame is still
213     // being drawn, then the implementation is free to silently ignore this call.
214     virtual void cleanupPostRender() = 0;
215 
216     // Returns the priority this context was actually created with. Note: this
217     // may not be the same as specified at context creation time, due to
218     // implementation limits on the number of contexts that can be created at a
219     // specific priority level in the system.
220     //
221     // This should return a valid EGL context priority enum as described by
222     // https://registry.khronos.org/EGL/extensions/IMG/EGL_IMG_context_priority.txt
223     // or
224     // https://registry.khronos.org/EGL/extensions/NV/EGL_NV_context_priority_realtime.txt
225     virtual int getContextPriority() = 0;
226 
227     // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation
228     // also supports background blur.  If false, no blur will be applied when drawing layers. This
229     // query is required to be thread safe.
230     virtual bool supportsBackgroundBlur() = 0;
231 
232     // TODO(b/180767535): This is only implemented to allow for backend-specific behavior, which
233     // we should not allow in general, so remove this.
isThreaded()234     bool isThreaded() const { return mThreaded == Threaded::YES; }
235 
236     static void validateInputBufferUsage(const sp<GraphicBuffer>&);
237     static void validateOutputBufferUsage(const sp<GraphicBuffer>&);
238 
239     // Allows flinger to get the render engine thread id for power management with ADPF
240     // Returns the tid of the renderengine thread if it's threaded, and std::nullopt otherwise
getRenderEngineTid()241     virtual std::optional<pid_t> getRenderEngineTid() const { return std::nullopt; }
242 
setEnableTracing(bool)243     virtual void setEnableTracing(bool /*tracingEnabled*/) {}
244 
245 protected:
RenderEngine()246     RenderEngine() : RenderEngine(Threaded::NO) {}
247 
RenderEngine(Threaded threaded)248     RenderEngine(Threaded threaded) : mThreaded(threaded) {}
249 
250     // Maps GPU resources for this buffer.
251     // Note that work may be deferred to an additional thread, i.e. this call
252     // is made asynchronously, but the caller can expect that map/unmap calls
253     // are performed in a manner that's conflict serializable, i.e. unmapping
254     // a buffer should never occur before binding the buffer if the caller
255     // called mapExternalTextureBuffer before calling unmap.
256     // Note also that if the buffer contains protected content, then mapping those GPU resources may
257     // be deferred until the buffer is really used for drawing. This is because typical SoCs that
258     // support protected memory only support a limited amount, so optimisitically mapping protected
259     // memory may be too burdensome. If a buffer contains protected content and the RenderEngine
260     // implementation supports protected context, then GPU resources may be mapped into both the
261     // protected and unprotected contexts.
262     // If the buffer may ever be written to by RenderEngine, then isRenderable must be true.
263     virtual void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) = 0;
264     // Unmaps GPU resources used by this buffer. This method should be
265     // invoked when the caller will no longer hold a reference to a GraphicBuffer
266     // and needs to clean up its resources.
267     // Note that if there are multiple callers holding onto the same buffer, then the buffer's
268     // resources may be internally ref-counted to guard against use-after-free errors. Note that
269     // work may be deferred to an additional thread, i.e. this call is expected to be made
270     // asynchronously, but the caller can expect that map/unmap calls are performed in a manner
271     // that's conflict serializable, i.e. unmap a buffer should never occur before binding the
272     // buffer if the caller called mapExternalTextureBuffer before calling unmap.
273     virtual void unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) = 0;
274 
275     // A thread safe query to determine if any post rendering cleanup is necessary.  Returning true
276     // is a signal that calling the postRenderCleanup method would be a no-op and that callers can
277     // avoid any thread synchronization that may be required by directly calling postRenderCleanup.
278     virtual bool canSkipPostRenderCleanup() const = 0;
279 
280     friend class impl::ExternalTexture;
281     friend class threaded::RenderEngineThreaded;
282     friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test;
283     const Threaded mThreaded;
284 
285     // Update protectedContext mode depending on whether or not any layer has a protected buffer.
286     void updateProtectedContext(const std::vector<LayerSettings>&,
287                                 const std::shared_ptr<ExternalTexture>&);
288 
289     // Attempt to switch RenderEngine into and out of protectedContext mode
290     virtual void useProtectedContext(bool useProtectedContext) = 0;
291 
292     virtual void drawLayersInternal(
293             const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
294             const DisplaySettings& display, const std::vector<LayerSettings>& layers,
295             const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) = 0;
296 };
297 
298 struct RenderEngineCreationArgs {
299     int pixelFormat;
300     uint32_t imageCacheSize;
301     bool useColorManagement;
302     bool enableProtectedContext;
303     bool precacheToneMapperShaderOnly;
304     RenderEngine::BlurAlgorithm blurAlgorithm;
305     RenderEngine::ContextPriority contextPriority;
306     RenderEngine::Threaded threaded;
307     RenderEngine::GraphicsApi graphicsApi;
308     RenderEngine::SkiaBackend skiaBackend;
309 
310     struct Builder;
311 
312 private:
313     // must be created by Builder via constructor with full argument list
RenderEngineCreationArgsRenderEngineCreationArgs314     RenderEngineCreationArgs(int _pixelFormat, uint32_t _imageCacheSize,
315                              bool _enableProtectedContext, bool _precacheToneMapperShaderOnly,
316                              RenderEngine::BlurAlgorithm _blurAlgorithm,
317                              RenderEngine::ContextPriority _contextPriority,
318                              RenderEngine::Threaded _threaded,
319                              RenderEngine::GraphicsApi _graphicsApi,
320                              RenderEngine::SkiaBackend _skiaBackend)
321           : pixelFormat(_pixelFormat),
322             imageCacheSize(_imageCacheSize),
323             enableProtectedContext(_enableProtectedContext),
324             precacheToneMapperShaderOnly(_precacheToneMapperShaderOnly),
325             blurAlgorithm(_blurAlgorithm),
326             contextPriority(_contextPriority),
327             threaded(_threaded),
328             graphicsApi(_graphicsApi),
329             skiaBackend(_skiaBackend) {}
330     RenderEngineCreationArgs() = delete;
331 };
332 
333 struct RenderEngineCreationArgs::Builder {
BuilderBuilder334     Builder() {}
335 
setPixelFormatBuilder336     Builder& setPixelFormat(int pixelFormat) {
337         this->pixelFormat = pixelFormat;
338         return *this;
339     }
setImageCacheSizeBuilder340     Builder& setImageCacheSize(uint32_t imageCacheSize) {
341         this->imageCacheSize = imageCacheSize;
342         return *this;
343     }
setEnableProtectedContextBuilder344     Builder& setEnableProtectedContext(bool enableProtectedContext) {
345         this->enableProtectedContext = enableProtectedContext;
346         return *this;
347     }
setPrecacheToneMapperShaderOnlyBuilder348     Builder& setPrecacheToneMapperShaderOnly(bool precacheToneMapperShaderOnly) {
349         this->precacheToneMapperShaderOnly = precacheToneMapperShaderOnly;
350         return *this;
351     }
setBlurAlgorithmBuilder352     Builder& setBlurAlgorithm(RenderEngine::BlurAlgorithm blurAlgorithm) {
353         this->blurAlgorithm = blurAlgorithm;
354         return *this;
355     }
setContextPriorityBuilder356     Builder& setContextPriority(RenderEngine::ContextPriority contextPriority) {
357         this->contextPriority = contextPriority;
358         return *this;
359     }
setThreadedBuilder360     Builder& setThreaded(RenderEngine::Threaded threaded) {
361         this->threaded = threaded;
362         return *this;
363     }
setGraphicsApiBuilder364     Builder& setGraphicsApi(RenderEngine::GraphicsApi graphicsApi) {
365         this->graphicsApi = graphicsApi;
366         return *this;
367     }
setSkiaBackendBuilder368     Builder& setSkiaBackend(RenderEngine::SkiaBackend skiaBackend) {
369         this->skiaBackend = skiaBackend;
370         return *this;
371     }
buildBuilder372     RenderEngineCreationArgs build() const {
373         return RenderEngineCreationArgs(pixelFormat, imageCacheSize, enableProtectedContext,
374                                         precacheToneMapperShaderOnly, blurAlgorithm,
375                                         contextPriority, threaded, graphicsApi, skiaBackend);
376     }
377 
378 private:
379     // 1 means RGBA_8888
380     int pixelFormat = 1;
381     uint32_t imageCacheSize = 0;
382     bool enableProtectedContext = false;
383     bool precacheToneMapperShaderOnly = false;
384     RenderEngine::BlurAlgorithm blurAlgorithm = RenderEngine::BlurAlgorithm::NONE;
385     RenderEngine::ContextPriority contextPriority = RenderEngine::ContextPriority::MEDIUM;
386     RenderEngine::Threaded threaded = RenderEngine::Threaded::YES;
387     RenderEngine::GraphicsApi graphicsApi = RenderEngine::GraphicsApi::GL;
388     RenderEngine::SkiaBackend skiaBackend = RenderEngine::SkiaBackend::GANESH;
389 };
390 
391 } // namespace renderengine
392 } // namespace android
393 
394 #endif /* SF_RENDERENGINE_H_ */
395