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