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