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 virtual ftl::Future<FenceResult> drawGainmap(const std::shared_ptr<ExternalTexture>& sdr, 221 base::borrowed_fd&& sdrFence, 222 const std::shared_ptr<ExternalTexture>& hdr, 223 base::borrowed_fd&& hdrFence, float hdrSdrRatio, 224 ui::Dataspace dataspace, 225 const std::shared_ptr<ExternalTexture>& gainmap); 226 227 // Clean-up method that should be called on the main thread after the 228 // drawFence returned by drawLayers fires. This method will free up 229 // resources used by the most recently drawn frame. If the frame is still 230 // being drawn, then the implementation is free to silently ignore this call. 231 virtual void cleanupPostRender() = 0; 232 233 // Returns the priority this context was actually created with. Note: this 234 // may not be the same as specified at context creation time, due to 235 // implementation limits on the number of contexts that can be created at a 236 // specific priority level in the system. 237 // 238 // This should return a valid EGL context priority enum as described by 239 // https://registry.khronos.org/EGL/extensions/IMG/EGL_IMG_context_priority.txt 240 // or 241 // https://registry.khronos.org/EGL/extensions/NV/EGL_NV_context_priority_realtime.txt 242 virtual int getContextPriority() = 0; 243 244 // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation 245 // also supports background blur. If false, no blur will be applied when drawing layers. This 246 // query is required to be thread safe. 247 virtual bool supportsBackgroundBlur() = 0; 248 249 // TODO(b/180767535): This is only implemented to allow for backend-specific behavior, which 250 // we should not allow in general, so remove this. isThreaded()251 bool isThreaded() const { return mThreaded == Threaded::YES; } 252 253 static void validateInputBufferUsage(const sp<GraphicBuffer>&); 254 static void validateOutputBufferUsage(const sp<GraphicBuffer>&); 255 256 // Allows flinger to get the render engine thread id for power management with ADPF 257 // Returns the tid of the renderengine thread if it's threaded, and std::nullopt otherwise getRenderEngineTid()258 virtual std::optional<pid_t> getRenderEngineTid() const { return std::nullopt; } 259 setEnableTracing(bool)260 virtual void setEnableTracing(bool /*tracingEnabled*/) {} 261 262 protected: RenderEngine()263 RenderEngine() : RenderEngine(Threaded::NO) {} 264 RenderEngine(Threaded threaded)265 RenderEngine(Threaded threaded) : mThreaded(threaded) {} 266 267 // Maps GPU resources for this buffer. 268 // Note that work may be deferred to an additional thread, i.e. this call 269 // is made asynchronously, but the caller can expect that map/unmap calls 270 // are performed in a manner that's conflict serializable, i.e. unmapping 271 // a buffer should never occur before binding the buffer if the caller 272 // called mapExternalTextureBuffer before calling unmap. 273 // Note also that if the buffer contains protected content, then mapping those GPU resources may 274 // be deferred until the buffer is really used for drawing. This is because typical SoCs that 275 // support protected memory only support a limited amount, so optimisitically mapping protected 276 // memory may be too burdensome. If a buffer contains protected content and the RenderEngine 277 // implementation supports protected context, then GPU resources may be mapped into both the 278 // protected and unprotected contexts. 279 // If the buffer may ever be written to by RenderEngine, then isRenderable must be true. 280 virtual void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) = 0; 281 // Unmaps GPU resources used by this buffer. This method should be 282 // invoked when the caller will no longer hold a reference to a GraphicBuffer 283 // and needs to clean up its resources. 284 // Note that if there are multiple callers holding onto the same buffer, then the buffer's 285 // resources may be internally ref-counted to guard against use-after-free errors. Note that 286 // work may be deferred to an additional thread, i.e. this call is expected to be made 287 // asynchronously, but the caller can expect that map/unmap calls are performed in a manner 288 // that's conflict serializable, i.e. unmap a buffer should never occur before binding the 289 // buffer if the caller called mapExternalTextureBuffer before calling unmap. 290 virtual void unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) = 0; 291 292 // A thread safe query to determine if any post rendering cleanup is necessary. Returning true 293 // is a signal that calling the postRenderCleanup method would be a no-op and that callers can 294 // avoid any thread synchronization that may be required by directly calling postRenderCleanup. 295 virtual bool canSkipPostRenderCleanup() const = 0; 296 297 friend class impl::ExternalTexture; 298 friend class threaded::RenderEngineThreaded; 299 friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test; 300 const Threaded mThreaded; 301 302 // Update protectedContext mode depending on whether or not any layer has a protected buffer. 303 void updateProtectedContext(const std::vector<LayerSettings>&, 304 std::vector<const ExternalTexture*>); 305 // Attempt to switch RenderEngine into and out of protectedContext mode 306 virtual void useProtectedContext(bool useProtectedContext) = 0; 307 308 virtual void drawLayersInternal( 309 const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, 310 const DisplaySettings& display, const std::vector<LayerSettings>& layers, 311 const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) = 0; 312 313 virtual void drawGainmapInternal( 314 const std::shared_ptr<std::promise<FenceResult>>&& resultPromise, 315 const std::shared_ptr<ExternalTexture>& sdr, base::borrowed_fd&& sdrFence, 316 const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence, 317 float hdrSdrRatio, ui::Dataspace dataspace, 318 const std::shared_ptr<ExternalTexture>& gainmap) = 0; 319 }; 320 321 struct RenderEngineCreationArgs { 322 int pixelFormat; 323 uint32_t imageCacheSize; 324 bool useColorManagement; 325 bool enableProtectedContext; 326 bool precacheToneMapperShaderOnly; 327 RenderEngine::BlurAlgorithm blurAlgorithm; 328 RenderEngine::ContextPriority contextPriority; 329 RenderEngine::Threaded threaded; 330 RenderEngine::GraphicsApi graphicsApi; 331 RenderEngine::SkiaBackend skiaBackend; 332 333 struct Builder; 334 335 private: 336 // must be created by Builder via constructor with full argument list RenderEngineCreationArgsRenderEngineCreationArgs337 RenderEngineCreationArgs(int _pixelFormat, uint32_t _imageCacheSize, 338 bool _enableProtectedContext, bool _precacheToneMapperShaderOnly, 339 RenderEngine::BlurAlgorithm _blurAlgorithm, 340 RenderEngine::ContextPriority _contextPriority, 341 RenderEngine::Threaded _threaded, 342 RenderEngine::GraphicsApi _graphicsApi, 343 RenderEngine::SkiaBackend _skiaBackend) 344 : pixelFormat(_pixelFormat), 345 imageCacheSize(_imageCacheSize), 346 enableProtectedContext(_enableProtectedContext), 347 precacheToneMapperShaderOnly(_precacheToneMapperShaderOnly), 348 blurAlgorithm(_blurAlgorithm), 349 contextPriority(_contextPriority), 350 threaded(_threaded), 351 graphicsApi(_graphicsApi), 352 skiaBackend(_skiaBackend) {} 353 RenderEngineCreationArgs() = delete; 354 }; 355 356 struct RenderEngineCreationArgs::Builder { BuilderBuilder357 Builder() {} 358 setPixelFormatBuilder359 Builder& setPixelFormat(int pixelFormat) { 360 this->pixelFormat = pixelFormat; 361 return *this; 362 } setImageCacheSizeBuilder363 Builder& setImageCacheSize(uint32_t imageCacheSize) { 364 this->imageCacheSize = imageCacheSize; 365 return *this; 366 } setEnableProtectedContextBuilder367 Builder& setEnableProtectedContext(bool enableProtectedContext) { 368 this->enableProtectedContext = enableProtectedContext; 369 return *this; 370 } setPrecacheToneMapperShaderOnlyBuilder371 Builder& setPrecacheToneMapperShaderOnly(bool precacheToneMapperShaderOnly) { 372 this->precacheToneMapperShaderOnly = precacheToneMapperShaderOnly; 373 return *this; 374 } setBlurAlgorithmBuilder375 Builder& setBlurAlgorithm(RenderEngine::BlurAlgorithm blurAlgorithm) { 376 this->blurAlgorithm = blurAlgorithm; 377 return *this; 378 } setContextPriorityBuilder379 Builder& setContextPriority(RenderEngine::ContextPriority contextPriority) { 380 this->contextPriority = contextPriority; 381 return *this; 382 } setThreadedBuilder383 Builder& setThreaded(RenderEngine::Threaded threaded) { 384 this->threaded = threaded; 385 return *this; 386 } setGraphicsApiBuilder387 Builder& setGraphicsApi(RenderEngine::GraphicsApi graphicsApi) { 388 this->graphicsApi = graphicsApi; 389 return *this; 390 } setSkiaBackendBuilder391 Builder& setSkiaBackend(RenderEngine::SkiaBackend skiaBackend) { 392 this->skiaBackend = skiaBackend; 393 return *this; 394 } buildBuilder395 RenderEngineCreationArgs build() const { 396 return RenderEngineCreationArgs(pixelFormat, imageCacheSize, enableProtectedContext, 397 precacheToneMapperShaderOnly, blurAlgorithm, 398 contextPriority, threaded, graphicsApi, skiaBackend); 399 } 400 401 private: 402 // 1 means RGBA_8888 403 int pixelFormat = 1; 404 uint32_t imageCacheSize = 0; 405 bool enableProtectedContext = false; 406 bool precacheToneMapperShaderOnly = false; 407 RenderEngine::BlurAlgorithm blurAlgorithm = RenderEngine::BlurAlgorithm::NONE; 408 RenderEngine::ContextPriority contextPriority = RenderEngine::ContextPriority::MEDIUM; 409 RenderEngine::Threaded threaded = RenderEngine::Threaded::YES; 410 RenderEngine::GraphicsApi graphicsApi = RenderEngine::GraphicsApi::GL; 411 RenderEngine::SkiaBackend skiaBackend = RenderEngine::SkiaBackend::GANESH; 412 }; 413 414 } // namespace renderengine 415 } // namespace android 416 417 #endif /* SF_RENDERENGINE_H_ */ 418