• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Allows opting particular devices into an initial preview rollout of RenderEngine on Graphite.
42  *
43  * Only applicable within SurfaceFlinger, and if relevant aconfig flags are enabled.
44  */
45 #define PROPERTY_DEBUG_RENDERENGINE_GRAPHITE_PREVIEW_OPTIN \
46     "debug.renderengine.graphite_preview_optin"
47 
48 /**
49  * Turns on recording of skia commands in SkiaGL version of the RE. This property
50  * defines number of milliseconds for the recording to take place. A non zero value
51  * turns on the recording.
52  */
53 #define PROPERTY_DEBUG_RENDERENGINE_CAPTURE_SKIA_MS "debug.renderengine.capture_skia_ms"
54 
55 /**
56  * Set to the most recently saved file once the capture is finished.
57  */
58 #define PROPERTY_DEBUG_RENDERENGINE_CAPTURE_FILENAME "debug.renderengine.capture_filename"
59 
60 /**
61  * Switches the cross-window background blur algorithm.
62  */
63 #define PROPERTY_DEBUG_RENDERENGINE_BLUR_ALGORITHM "debug.renderengine.blur_algorithm"
64 
65 /**
66  * Allows recording of Skia drawing commands with systrace.
67  */
68 #define PROPERTY_SKIA_ATRACE_ENABLED "debug.renderengine.skia_atrace_enabled"
69 
70 struct ANativeWindowBuffer;
71 
72 namespace android {
73 
74 class Rect;
75 class Region;
76 
77 namespace renderengine {
78 
79 class ExternalTexture;
80 class Image;
81 class Mesh;
82 class Texture;
83 struct RenderEngineCreationArgs;
84 
85 namespace threaded {
86 class RenderEngineThreaded;
87 }
88 
89 namespace impl {
90 class RenderEngine;
91 class ExternalTexture;
92 }
93 
94 enum class Protection {
95     UNPROTECTED = 1,
96     PROTECTED = 2,
97 };
98 
99 // Toggles for skipping or enabling priming of particular shaders.
100 struct PrimeCacheConfig {
101     bool cacheHolePunchLayer = true;
102     bool cacheSolidLayers = true;
103     bool cacheSolidDimmedLayers = true;
104     bool cacheImageLayers = true;
105     bool cacheImageDimmedLayers = true;
106     bool cacheClippedLayers = true;
107     bool cacheShadowLayers = true;
108     bool cacheEdgeExtension = true;
109     bool cachePIPImageLayers = true;
110     bool cacheTransparentImageDimmedLayers = true;
111     bool cacheClippedDimmedImageLayers = true;
112     bool cacheUltraHDR = true;
113 };
114 
115 class RenderEngine {
116 public:
117     enum class ContextPriority {
118         LOW = 1,
119         MEDIUM = 2,
120         HIGH = 3,
121         REALTIME = 4,
122     };
123 
124     enum class Threaded {
125         NO,
126         YES,
127     };
128 
129     enum class GraphicsApi {
130         GL,
131         VK,
132     };
133 
134     enum class SkiaBackend {
135         GANESH,
136         GRAPHITE,
137     };
138 
139     enum class BlurAlgorithm {
140         NONE,
141         GAUSSIAN,
142         KAWASE,
143         KAWASE_DUAL_FILTER,
144     };
145 
146     static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args);
147 
148     // Check if the device supports the given GraphicsApi.
149     //
150     // If called for GraphicsApi::VK then underlying (unprotected) VK resources will be preserved
151     // to optimize subsequent VK initialization, but teardown(GraphicsApi::VK) must be invoked if
152     // the caller subsequently decides to NOT use VK.
153     //
154     // The first call may require significant resource initialization, but subsequent checks are
155     // cached internally.
156     static bool canSupport(GraphicsApi graphicsApi);
157 
158     // Teardown any GPU API resources that were previously initialized but are no longer needed.
159     //
160     // Must be called with GraphicsApi::VK if canSupport(GraphicsApi::VK) was previously invoked but
161     // the caller subsequently decided to not use VK.
162     //
163     // This is safe to call if there is nothing to teardown, but NOT safe to call if a RenderEngine
164     // instance exists. The RenderEngine destructor will handle its own teardown logic.
165     static void teardown(GraphicsApi graphicsApi);
166 
167     virtual ~RenderEngine() = 0;
168 
169     // ----- BEGIN DEPRECATED INTERFACE -----
170     // This interface, while still in use until a suitable replacement is built,
171     // should be considered deprecated, minus some methods which still may be
172     // used to support legacy behavior.
173     virtual std::future<void> primeCache(PrimeCacheConfig config) = 0;
174 
175     // dump the extension strings. always call the base class.
176     virtual void dump(std::string& result) = 0;
177 
178     // queries that are required to be thread safe
179     virtual size_t getMaxTextureSize() const = 0;
180     virtual size_t getMaxViewportDims() const = 0;
181 
182     // ----- END DEPRECATED INTERFACE -----
183 
184     // ----- BEGIN NEW INTERFACE -----
185 
186     // queries that are required to be thread safe
187     virtual bool supportsProtectedContent() const = 0;
188 
189     // Notify RenderEngine of changes to the dimensions of the active display
190     // so that it can configure its internal caches accordingly.
191     virtual void onActiveDisplaySizeChanged(ui::Size size) = 0;
192 
193     // Renders layers for a particular display via GPU composition. This method
194     // should be called for every display that needs to be rendered via the GPU.
195     // @param display The display-wide settings that should be applied prior to
196     // drawing any layers.
197     //
198     // Assumptions when calling this method:
199     // 1. There is exactly one caller - i.e. multi-threading is not supported.
200     // 2. Additional threads may be calling the {bind,cache}ExternalTexture
201     // methods above. But the main thread is responsible for holding resources
202     // such that Image destruction does not occur while this method is called.
203     //
204     // TODO(b/136806342): This should behavior should ideally be fixed since
205     // the above two assumptions are brittle, as conditional thread safetyness
206     // may be insufficient when maximizing rendering performance in the future.
207     //
208     // @param layers The layers to draw onto the display, in Z-order.
209     // @param buffer The buffer which will be drawn to. This buffer will be
210     // ready once drawFence fires.
211     // @param bufferFence Fence signalling that the buffer is ready to be drawn
212     // to.
213     // @return A future object of FenceResult indicating whether drawing was
214     // successful in async mode.
215     virtual ftl::Future<FenceResult> drawLayers(const DisplaySettings& display,
216                                                 const std::vector<LayerSettings>& layers,
217                                                 const std::shared_ptr<ExternalTexture>& buffer,
218                                                 base::unique_fd&& bufferFence);
219 
220     // Tonemaps an HDR input image and draws an SDR rendition, plus a gainmap
221     // describing how to recover the HDR image.
222     //
223     // The HDR input image is ALWAYS encoded with an sRGB transfer function and
224     // is a floating point format. Accordingly, the hdrSdrRatio describes the
225     // max luminance in the HDR input image above SDR, and the dataspace
226     // describes the input primaries.
227     virtual ftl::Future<FenceResult> tonemapAndDrawGainmap(
228             const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
229             float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
230             const std::shared_ptr<ExternalTexture>& gainmap);
231 
232     // Clean-up method that should be called on the main thread after the
233     // drawFence returned by drawLayers fires. This method will free up
234     // resources used by the most recently drawn frame. If the frame is still
235     // being drawn, then the implementation is free to silently ignore this call.
236     virtual void cleanupPostRender() = 0;
237 
238     // Returns the priority this context was actually created with. Note: this
239     // may not be the same as specified at context creation time, due to
240     // implementation limits on the number of contexts that can be created at a
241     // specific priority level in the system.
242     //
243     // This should return a valid EGL context priority enum as described by
244     // https://registry.khronos.org/EGL/extensions/IMG/EGL_IMG_context_priority.txt
245     // or
246     // https://registry.khronos.org/EGL/extensions/NV/EGL_NV_context_priority_realtime.txt
247     virtual int getContextPriority() = 0;
248 
249     // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation
250     // also supports background blur.  If false, no blur will be applied when drawing layers. This
251     // query is required to be thread safe.
252     virtual bool supportsBackgroundBlur() = 0;
253 
254     // TODO(b/180767535): This is only implemented to allow for backend-specific behavior, which
255     // we should not allow in general, so remove this.
isThreaded()256     bool isThreaded() const { return mThreaded == Threaded::YES; }
257 
258     static void validateInputBufferUsage(const sp<GraphicBuffer>&);
259     static void validateOutputBufferUsage(const sp<GraphicBuffer>&);
260 
261     // Allows flinger to get the render engine thread id for power management with ADPF
262     // Returns the tid of the renderengine thread if it's threaded, and std::nullopt otherwise
getRenderEngineTid()263     virtual std::optional<pid_t> getRenderEngineTid() const { return std::nullopt; }
264 
setEnableTracing(bool)265     virtual void setEnableTracing(bool /*tracingEnabled*/) {}
266 
267 protected:
RenderEngine()268     RenderEngine() : RenderEngine(Threaded::NO) {}
269 
RenderEngine(Threaded threaded)270     RenderEngine(Threaded threaded) : mThreaded(threaded) {}
271 
272     // Maps GPU resources for this buffer.
273     // Note that work may be deferred to an additional thread, i.e. this call
274     // is made asynchronously, but the caller can expect that map/unmap calls
275     // are performed in a manner that's conflict serializable, i.e. unmapping
276     // a buffer should never occur before binding the buffer if the caller
277     // called mapExternalTextureBuffer before calling unmap.
278     // Note also that if the buffer contains protected content, then mapping those GPU resources may
279     // be deferred until the buffer is really used for drawing. This is because typical SoCs that
280     // support protected memory only support a limited amount, so optimisitically mapping protected
281     // memory may be too burdensome. If a buffer contains protected content and the RenderEngine
282     // implementation supports protected context, then GPU resources may be mapped into both the
283     // protected and unprotected contexts.
284     // If the buffer may ever be written to by RenderEngine, then isRenderable must be true.
285     virtual void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) = 0;
286     // Unmaps GPU resources used by this buffer. This method should be
287     // invoked when the caller will no longer hold a reference to a GraphicBuffer
288     // and needs to clean up its resources.
289     // Note that if there are multiple callers holding onto the same buffer, then the buffer's
290     // resources may be internally ref-counted to guard against use-after-free errors. Note that
291     // work may be deferred to an additional thread, i.e. this call is expected to be made
292     // asynchronously, but the caller can expect that map/unmap calls are performed in a manner
293     // that's conflict serializable, i.e. unmap a buffer should never occur before binding the
294     // buffer if the caller called mapExternalTextureBuffer before calling unmap.
295     virtual void unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) = 0;
296 
297     // A thread safe query to determine if any post rendering cleanup is necessary.  Returning true
298     // is a signal that calling the postRenderCleanup method would be a no-op and that callers can
299     // avoid any thread synchronization that may be required by directly calling postRenderCleanup.
300     virtual bool canSkipPostRenderCleanup() const = 0;
301 
302     friend class impl::ExternalTexture;
303     friend class threaded::RenderEngineThreaded;
304     friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test;
305     const Threaded mThreaded;
306 
307     // Update protectedContext mode depending on whether or not any layer has a protected buffer.
308     void updateProtectedContext(const std::vector<LayerSettings>&,
309                                 std::vector<const ExternalTexture*>);
310     // Attempt to switch RenderEngine into and out of protectedContext mode
311     virtual void useProtectedContext(bool useProtectedContext) = 0;
312 
313     virtual void drawLayersInternal(
314             const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
315             const DisplaySettings& display, const std::vector<LayerSettings>& layers,
316             const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) = 0;
317 
318     virtual void tonemapAndDrawGainmapInternal(
319             const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
320             const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
321             float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
322             const std::shared_ptr<ExternalTexture>& gainmap) = 0;
323 };
324 
325 struct RenderEngineCreationArgs {
326     int pixelFormat;
327     uint32_t imageCacheSize;
328     bool useColorManagement;
329     bool enableProtectedContext;
330     bool precacheToneMapperShaderOnly;
331     RenderEngine::BlurAlgorithm blurAlgorithm;
332     RenderEngine::ContextPriority contextPriority;
333     RenderEngine::Threaded threaded;
334     RenderEngine::GraphicsApi graphicsApi;
335     RenderEngine::SkiaBackend skiaBackend;
336 
337     struct Builder;
338 
339 private:
340     // must be created by Builder via constructor with full argument list
RenderEngineCreationArgsRenderEngineCreationArgs341     RenderEngineCreationArgs(int _pixelFormat, uint32_t _imageCacheSize,
342                              bool _enableProtectedContext, bool _precacheToneMapperShaderOnly,
343                              RenderEngine::BlurAlgorithm _blurAlgorithm,
344                              RenderEngine::ContextPriority _contextPriority,
345                              RenderEngine::Threaded _threaded,
346                              RenderEngine::GraphicsApi _graphicsApi,
347                              RenderEngine::SkiaBackend _skiaBackend)
348           : pixelFormat(_pixelFormat),
349             imageCacheSize(_imageCacheSize),
350             enableProtectedContext(_enableProtectedContext),
351             precacheToneMapperShaderOnly(_precacheToneMapperShaderOnly),
352             blurAlgorithm(_blurAlgorithm),
353             contextPriority(_contextPriority),
354             threaded(_threaded),
355             graphicsApi(_graphicsApi),
356             skiaBackend(_skiaBackend) {}
357     RenderEngineCreationArgs() = delete;
358 };
359 
360 struct RenderEngineCreationArgs::Builder {
BuilderBuilder361     Builder() {}
362 
setPixelFormatBuilder363     Builder& setPixelFormat(int pixelFormat) {
364         this->pixelFormat = pixelFormat;
365         return *this;
366     }
setImageCacheSizeBuilder367     Builder& setImageCacheSize(uint32_t imageCacheSize) {
368         this->imageCacheSize = imageCacheSize;
369         return *this;
370     }
setEnableProtectedContextBuilder371     Builder& setEnableProtectedContext(bool enableProtectedContext) {
372         this->enableProtectedContext = enableProtectedContext;
373         return *this;
374     }
setPrecacheToneMapperShaderOnlyBuilder375     Builder& setPrecacheToneMapperShaderOnly(bool precacheToneMapperShaderOnly) {
376         this->precacheToneMapperShaderOnly = precacheToneMapperShaderOnly;
377         return *this;
378     }
setBlurAlgorithmBuilder379     Builder& setBlurAlgorithm(RenderEngine::BlurAlgorithm blurAlgorithm) {
380         this->blurAlgorithm = blurAlgorithm;
381         return *this;
382     }
setContextPriorityBuilder383     Builder& setContextPriority(RenderEngine::ContextPriority contextPriority) {
384         this->contextPriority = contextPriority;
385         return *this;
386     }
setThreadedBuilder387     Builder& setThreaded(RenderEngine::Threaded threaded) {
388         this->threaded = threaded;
389         return *this;
390     }
setGraphicsApiBuilder391     Builder& setGraphicsApi(RenderEngine::GraphicsApi graphicsApi) {
392         this->graphicsApi = graphicsApi;
393         return *this;
394     }
setSkiaBackendBuilder395     Builder& setSkiaBackend(RenderEngine::SkiaBackend skiaBackend) {
396         this->skiaBackend = skiaBackend;
397         return *this;
398     }
buildBuilder399     RenderEngineCreationArgs build() const {
400         return RenderEngineCreationArgs(pixelFormat, imageCacheSize, enableProtectedContext,
401                                         precacheToneMapperShaderOnly, blurAlgorithm,
402                                         contextPriority, threaded, graphicsApi, skiaBackend);
403     }
404 
405 private:
406     // 1 means RGBA_8888
407     int pixelFormat = 1;
408     uint32_t imageCacheSize = 0;
409     bool enableProtectedContext = false;
410     bool precacheToneMapperShaderOnly = false;
411     RenderEngine::BlurAlgorithm blurAlgorithm = RenderEngine::BlurAlgorithm::NONE;
412     RenderEngine::ContextPriority contextPriority = RenderEngine::ContextPriority::MEDIUM;
413     RenderEngine::Threaded threaded = RenderEngine::Threaded::YES;
414     RenderEngine::GraphicsApi graphicsApi = RenderEngine::GraphicsApi::GL;
415     RenderEngine::SkiaBackend skiaBackend = RenderEngine::SkiaBackend::GANESH;
416 };
417 
418 } // namespace renderengine
419 } // namespace android
420 
421 #endif /* SF_RENDERENGINE_H_ */
422