Loading services/surfaceflinger/SurfaceFlinger.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -384,6 +384,7 @@ bool SurfaceFlinger::useHwcForRgbToYuv; bool SurfaceFlinger::hasSyncFramework; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; int64_t SurfaceFlinger::minAcquiredBuffers = 1; std::optional<int64_t> SurfaceFlinger::maxAcquiredBuffersOpt; uint32_t SurfaceFlinger::maxGraphicsWidth; uint32_t SurfaceFlinger::maxGraphicsHeight; bool SurfaceFlinger::useContextPriority; Loading Loading @@ -452,6 +453,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); minAcquiredBuffers = SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers); maxAcquiredBuffersOpt = SurfaceFlingerProperties::max_acquired_buffers(); maxGraphicsWidth = std::max(max_graphics_width(0), 0); maxGraphicsHeight = std::max(max_graphics_height(0), 0); Loading Loading @@ -8240,11 +8242,13 @@ int SurfaceFlinger::getGpuContextPriority() { int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) { auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); int64_t pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); if (presentLatency.count() % refreshRate.getPeriodNsecs()) { pipelineDepth++; } return std::max(minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1)); const int64_t maxAcquiredBuffers = std::min(pipelineDepth - 1, maxAcquiredBuffersOpt.value_or(pipelineDepth - 1)); return std::max(minAcquiredBuffers, maxAcquiredBuffers); } status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const { Loading services/surfaceflinger/SurfaceFlinger.h +5 −0 Original line number Diff line number Diff line Loading @@ -238,6 +238,11 @@ public: // ISurfaceComposer.getMaxAcquiredBufferCount(). static int64_t minAcquiredBuffers; // Controls the maximum acquired buffers SurfaceFlinger will suggest via // ISurfaceComposer.getMaxAcquiredBufferCount(). // Value is set through ro.surface_flinger.max_acquired_buffers. static std::optional<int64_t> maxAcquiredBuffersOpt; // Controls the maximum width and height in pixels that the graphics pipeline can support for // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs. static uint32_t maxGraphicsWidth; Loading services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +10 −0 Original line number Diff line number Diff line Loading @@ -483,6 +483,16 @@ prop { prop_name: "ro.surface_flinger.min_acquired_buffers" } # Defines the maximum acquired buffers SurfaceFlinger will suggest via # ISurfaceComposer.getMaxAcquiredBufferCount(). prop { api_name: "max_acquired_buffers" type: Long scope: Public access: Readonly prop_name: "ro.surface_flinger.max_acquired_buffers" } # When enabled, SurfaceFlinger will attempt to clear the per-layer HAL buffer cache slots for # buffers when they are evicted from the app cache by using additional setLayerBuffer commands. # Ideally, this behavior would always be enabled to reduce graphics memory consumption. However, Loading services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,11 @@ props { api_name: "ignore_hdr_camera_layers" prop_name: "ro.surface_flinger.ignore_hdr_camera_layers" } prop { api_name: "max_acquired_buffers" type: Long prop_name: "ro.surface_flinger.max_acquired_buffers" } prop { api_name: "max_frame_buffer_acquired_buffers" type: Long Loading services/surfaceflinger/tests/unittests/SchedulerTest.cpp +31 −6 Original line number Diff line number Diff line Loading @@ -254,18 +254,43 @@ TEST_F(SchedulerTest, emitModeChangeEvent) { } TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms)); EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms)); EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms)); struct TestCase { Fps refreshRate; std::chrono::nanoseconds presentLatency; int expectedBufferCount; }; EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms)); const auto verifyTestCases = [&](std::vector<TestCase> tests) { for (const auto testCase : tests) { EXPECT_EQ(testCase.expectedBufferCount, mFlinger.calculateMaxAcquiredBufferCount(testCase.refreshRate, testCase.presentLatency)); } }; EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); std::vector<TestCase> testCases{{60_Hz, 30ms, 1}, {90_Hz, 30ms, 2}, {120_Hz, 30ms, 3}, {60_Hz, 40ms, 2}, {60_Hz, 10ms, 1}}; verifyTestCases(testCases); const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers(); mFlinger.mutableMinAcquiredBuffers() = 2; EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); verifyTestCases({{60_Hz, 10ms, 2}}); mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers; const auto savedMaxAcquiredBuffers = mFlinger.mutableMaxAcquiredBuffers(); mFlinger.mutableMaxAcquiredBuffers() = 2; testCases = {{60_Hz, 30ms, 1}, {90_Hz, 30ms, 2}, {120_Hz, 30ms, 2}, // max buffers allowed is 2 {60_Hz, 40ms, 2}, {60_Hz, 10ms, 1}}; verifyTestCases(testCases); mFlinger.mutableMaxAcquiredBuffers() = 3; // max buffers allowed is 3 verifyTestCases({{120_Hz, 30ms, 3}}); mFlinger.mutableMaxAcquiredBuffers() = savedMaxAcquiredBuffers; } MATCHER(Is120Hz, "") { Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -384,6 +384,7 @@ bool SurfaceFlinger::useHwcForRgbToYuv; bool SurfaceFlinger::hasSyncFramework; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; int64_t SurfaceFlinger::minAcquiredBuffers = 1; std::optional<int64_t> SurfaceFlinger::maxAcquiredBuffersOpt; uint32_t SurfaceFlinger::maxGraphicsWidth; uint32_t SurfaceFlinger::maxGraphicsHeight; bool SurfaceFlinger::useContextPriority; Loading Loading @@ -452,6 +453,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); minAcquiredBuffers = SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers); maxAcquiredBuffersOpt = SurfaceFlingerProperties::max_acquired_buffers(); maxGraphicsWidth = std::max(max_graphics_width(0), 0); maxGraphicsHeight = std::max(max_graphics_height(0), 0); Loading Loading @@ -8240,11 +8242,13 @@ int SurfaceFlinger::getGpuContextPriority() { int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) { auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); int64_t pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); if (presentLatency.count() % refreshRate.getPeriodNsecs()) { pipelineDepth++; } return std::max(minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1)); const int64_t maxAcquiredBuffers = std::min(pipelineDepth - 1, maxAcquiredBuffersOpt.value_or(pipelineDepth - 1)); return std::max(minAcquiredBuffers, maxAcquiredBuffers); } status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const { Loading
services/surfaceflinger/SurfaceFlinger.h +5 −0 Original line number Diff line number Diff line Loading @@ -238,6 +238,11 @@ public: // ISurfaceComposer.getMaxAcquiredBufferCount(). static int64_t minAcquiredBuffers; // Controls the maximum acquired buffers SurfaceFlinger will suggest via // ISurfaceComposer.getMaxAcquiredBufferCount(). // Value is set through ro.surface_flinger.max_acquired_buffers. static std::optional<int64_t> maxAcquiredBuffersOpt; // Controls the maximum width and height in pixels that the graphics pipeline can support for // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs. static uint32_t maxGraphicsWidth; Loading
services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +10 −0 Original line number Diff line number Diff line Loading @@ -483,6 +483,16 @@ prop { prop_name: "ro.surface_flinger.min_acquired_buffers" } # Defines the maximum acquired buffers SurfaceFlinger will suggest via # ISurfaceComposer.getMaxAcquiredBufferCount(). prop { api_name: "max_acquired_buffers" type: Long scope: Public access: Readonly prop_name: "ro.surface_flinger.max_acquired_buffers" } # When enabled, SurfaceFlinger will attempt to clear the per-layer HAL buffer cache slots for # buffers when they are evicted from the app cache by using additional setLayerBuffer commands. # Ideally, this behavior would always be enabled to reduce graphics memory consumption. However, Loading
services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,11 @@ props { api_name: "ignore_hdr_camera_layers" prop_name: "ro.surface_flinger.ignore_hdr_camera_layers" } prop { api_name: "max_acquired_buffers" type: Long prop_name: "ro.surface_flinger.max_acquired_buffers" } prop { api_name: "max_frame_buffer_acquired_buffers" type: Long Loading
services/surfaceflinger/tests/unittests/SchedulerTest.cpp +31 −6 Original line number Diff line number Diff line Loading @@ -254,18 +254,43 @@ TEST_F(SchedulerTest, emitModeChangeEvent) { } TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms)); EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms)); EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms)); struct TestCase { Fps refreshRate; std::chrono::nanoseconds presentLatency; int expectedBufferCount; }; EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms)); const auto verifyTestCases = [&](std::vector<TestCase> tests) { for (const auto testCase : tests) { EXPECT_EQ(testCase.expectedBufferCount, mFlinger.calculateMaxAcquiredBufferCount(testCase.refreshRate, testCase.presentLatency)); } }; EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); std::vector<TestCase> testCases{{60_Hz, 30ms, 1}, {90_Hz, 30ms, 2}, {120_Hz, 30ms, 3}, {60_Hz, 40ms, 2}, {60_Hz, 10ms, 1}}; verifyTestCases(testCases); const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers(); mFlinger.mutableMinAcquiredBuffers() = 2; EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); verifyTestCases({{60_Hz, 10ms, 2}}); mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers; const auto savedMaxAcquiredBuffers = mFlinger.mutableMaxAcquiredBuffers(); mFlinger.mutableMaxAcquiredBuffers() = 2; testCases = {{60_Hz, 30ms, 1}, {90_Hz, 30ms, 2}, {120_Hz, 30ms, 2}, // max buffers allowed is 2 {60_Hz, 40ms, 2}, {60_Hz, 10ms, 1}}; verifyTestCases(testCases); mFlinger.mutableMaxAcquiredBuffers() = 3; // max buffers allowed is 3 verifyTestCases({{120_Hz, 30ms, 3}}); mFlinger.mutableMaxAcquiredBuffers() = savedMaxAcquiredBuffers; } MATCHER(Is120Hz, "") { Loading