From a13f2d58e01d980d39d3617032120c5f9b6423bd Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Thu, 5 Mar 2020 11:54:17 +0100 Subject: Allow GPU composition to occur at a lower resolution Add a vendor-specified system property to allow GPU fallback composition to occur at a lower resolution than the display mode resolution. Bug: 144574809 Test: Tested with sysprop disabled, and tested backport in Android Q with sysprop enabled. Unable to test on Android R due to device issues. Change-Id: I02948ce72f49d20416d0e4dd45a4cffe99e28820 --- .../DisplayHardware/FramebufferSurface.cpp | 38 +++++++++++++++++++--- .../DisplayHardware/FramebufferSurface.h | 17 ++++++++-- services/surfaceflinger/SurfaceFlinger.cpp | 8 ++++- services/surfaceflinger/SurfaceFlinger.h | 6 ++++ .../surfaceflinger/SurfaceFlingerProperties.cpp | 16 +++++++++ services/surfaceflinger/SurfaceFlingerProperties.h | 3 ++ .../sysprop/SurfaceFlingerProperties.sysprop | 20 ++++++++++++ .../api/SurfaceFlingerProperties-current.txt | 10 ++++++ 8 files changed, 110 insertions(+), 8 deletions(-) diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 36544b6653..aeffb0e185 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -57,9 +57,12 @@ using ui::Dataspace; */ FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId, - const sp& consumer) + const sp& consumer, + uint32_t maxWidth, uint32_t maxHeight) : ConsumerBase(consumer), mDisplayId(displayId), + mMaxWidth(maxWidth), + mMaxHeight(maxHeight), mCurrentBufferSlot(-1), mCurrentBuffer(), mCurrentFence(Fence::NO_FENCE), @@ -75,14 +78,16 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId, GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); const auto& activeConfig = mHwc.getActiveConfig(displayId); - mConsumer->setDefaultBufferSize(activeConfig->getWidth(), - activeConfig->getHeight()); + ui::Size limitedSize = + limitFramebufferSize(activeConfig->getWidth(), activeConfig->getHeight()); + mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height); mConsumer->setMaxAcquiredBufferCount( SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1); } -void FramebufferSurface::resizeBuffers(const uint32_t width, const uint32_t height) { - mConsumer->setDefaultBufferSize(width, height); +void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) { + ui::Size limitedSize = limitFramebufferSize(width, height); + mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height); } status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) { @@ -177,6 +182,29 @@ void FramebufferSurface::onFrameCommitted() { } } +ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) { + // TODO(b/149495759): Use the ui::Size constructor once it no longer is broken. + ui::Size framebufferSize; + framebufferSize.width = width; + framebufferSize.height = height; + bool wasLimited = true; + if (width > mMaxWidth && mMaxWidth != 0) { + float aspectRatio = float(width) / float(height); + framebufferSize.height = mMaxWidth / aspectRatio; + framebufferSize.width = mMaxWidth; + wasLimited = true; + } + if (height > mMaxHeight && mMaxHeight != 0) { + float aspectRatio = float(width) / float(height); + framebufferSize.height = mMaxHeight; + framebufferSize.width = mMaxHeight * aspectRatio; + wasLimited = true; + } + ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]", + framebufferSize.width, framebufferSize.height, width, height); + return framebufferSize; +} + void FramebufferSurface::dumpAsString(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat(" FramebufferSurface: dataspace: %s(%d)\n", diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 7f451a5ac6..a1859f33bb 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "DisplayIdentification.h" @@ -39,7 +40,8 @@ class HWComposer; class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface { public: FramebufferSurface(HWComposer& hwc, DisplayId displayId, - const sp& consumer); + const sp& consumer, uint32_t maxWidth, + uint32_t maxHeight); virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); @@ -47,7 +49,7 @@ public: virtual void onFrameCommitted(); virtual void dumpAsString(String8& result) const; - virtual void resizeBuffers(const uint32_t width, const uint32_t height); + virtual void resizeBuffers(uint32_t width, uint32_t height); virtual const sp& getClientTargetAcquireFence() const override; @@ -58,6 +60,9 @@ private: virtual void dumpLocked(String8& result, const char* prefix) const; + // Limits the width and height by the maximum width specified in the constructor. + ui::Size limitFramebufferSize(uint32_t width, uint32_t height); + // nextBuffer waits for and then latches the next buffer from the // BufferQueue and releases the previously latched buffer to the // BufferQueue. The new buffer is returned in the 'buffer' argument. @@ -66,6 +71,14 @@ private: const DisplayId mDisplayId; + // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of + // the device. + const uint32_t mMaxWidth; + + // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of + // the device. + const uint32_t mMaxHeight; + // mCurrentBufferIndex is the slot index of the current buffer or // INVALID_BUFFER_SLOT to indicate that either there is no current buffer // or the buffer is not associated with a slot. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 163a1c743b..5a7372787d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -217,6 +217,8 @@ uint64_t SurfaceFlinger::maxVirtualDisplaySize; bool SurfaceFlinger::hasSyncFramework; bool SurfaceFlinger::useVrFlinger; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; +uint32_t SurfaceFlinger::maxGraphicsWidth; +uint32_t SurfaceFlinger::maxGraphicsHeight; bool SurfaceFlinger::hasWideColorDisplay; ui::Rotation SurfaceFlinger::internalDisplayOrientation = ui::ROTATION_0; bool SurfaceFlinger::useColorManagement; @@ -283,6 +285,9 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); + maxGraphicsWidth = std::max(max_graphics_width(0), 0); + maxGraphicsHeight = std::max(max_graphics_height(0), 0); + hasWideColorDisplay = has_wide_color_display(false); useColorManagement = use_color_management(false); @@ -2593,7 +2598,8 @@ void SurfaceFlinger::processDisplayChangesLocked() { state.surface.get()); LOG_ALWAYS_FATAL_IF(!displayId); - dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer); + dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer, + maxGraphicsWidth, maxGraphicsHeight); producer = bqProducer; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e7f9930392..7586793081 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -225,6 +226,11 @@ public: // FramebufferSurface static int64_t maxFrameBufferAcquiredBuffers; + // 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; + static uint32_t maxGraphicsHeight; + // Indicate if a device has wide color gamut display. This is typically // found on devices with wide color gamut (e.g. Display-P3) display. static bool hasWideColorDisplay; diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp index f3352a5a24..9d78702a08 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.cpp +++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp @@ -70,6 +70,22 @@ int64_t max_frame_buffer_acquired_buffers(int64_t defaultValue) { defaultValue); } +int32_t max_graphics_width(int32_t defaultValue) { + auto temp = SurfaceFlingerProperties::max_graphics_width(); + if (temp.has_value()) { + return *temp; + } + return defaultValue; +} + +int32_t max_graphics_height(int32_t defaultValue) { + auto temp = SurfaceFlingerProperties::max_graphics_height(); + if (temp.has_value()) { + return *temp; + } + return defaultValue; +} + bool has_wide_color_display(bool defaultValue) { auto temp = SurfaceFlingerProperties::has_wide_color_display(); if (temp.has_value()) { diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h index 12c711abfc..c63adfe3c2 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.h +++ b/services/surfaceflinger/SurfaceFlingerProperties.h @@ -37,6 +37,9 @@ bool use_context_priority(bool defaultValue); int64_t max_frame_buffer_acquired_buffers(int64_t defaultValue); +int32_t max_graphics_width(int32_t defaultValue); +int32_t max_graphics_height(int32_t defaultValue); + bool has_wide_color_display(bool defaultValue); bool running_without_sync_framework(bool defaultValue); diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index 155f71877d..cfc301bd22 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -67,6 +67,26 @@ prop { prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers" } +# Controls the maximum width in pixels that the graphics pipeline can support for GPU fallback +# composition. For example, 8k displays with 4k GPUs, or 4k displays with 2k GPUs. +prop { + api_name: "max_graphics_width" + type: Integer + scope: System + access: Readonly + prop_name: "ro.surface_flinger.max_graphics_width" +} + +# Controls the maximum height in pixels that the graphics pipeline can support for GPU fallback +# composition. For example, 8k displays with 4k GPUs, or 4k displays with 2k GPUs. +prop { + api_name: "max_graphics_height" + type: Integer + scope: System + access: Readonly + prop_name: "ro.surface_flinger.max_graphics_height" +} + # hasWideColorDisplay indicates that the device has # or can support a wide-color display, e.g. color space # greater than sRGB. Typical display may have same diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt index e62c127062..ba60a7defb 100644 --- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt @@ -61,6 +61,16 @@ props { type: Long prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers" } + prop { + api_name: "max_graphics_height" + type: Integer + prop_name: "ro.surface_flinger.max_graphics_height" + } + prop { + api_name: "max_graphics_width" + type: Integer + prop_name: "ro.surface_flinger.max_graphics_width" + } prop { api_name: "max_virtual_display_dimension" type: Long -- cgit v1.2.3-59-g8ed1b