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
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 36544b6..aeffb0e 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -57,9 +57,12 @@
*/
FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer)
+ const sp<IGraphicBufferConsumer>& 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 @@
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 @@
}
}
+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 7f451a5..a1859f3 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -23,6 +23,7 @@
#include <compositionengine/DisplaySurface.h>
#include <compositionengine/impl/HwcBufferCache.h>
#include <gui/ConsumerBase.h>
+#include <ui/Size.h>
#include "DisplayIdentification.h"
@@ -39,7 +40,8 @@
class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, DisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer);
+ const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
+ uint32_t maxHeight);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
@@ -47,7 +49,7 @@
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<Fence>& getClientTargetAcquireFence() const override;
@@ -58,6 +60,9 @@
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 @@
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 163a1c7..5a73727 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -217,6 +217,8 @@
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 @@
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 @@
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 e7f9930..7586793 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -42,6 +42,7 @@
#include <system/graphics.h>
#include <ui/FenceTime.h>
#include <ui/PixelFormat.h>
+#include <ui/Size.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -225,6 +226,11 @@
// 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 f3352a5..9d78702 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -70,6 +70,22 @@
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 12c711a..c63adfe 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -37,6 +37,9 @@
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 155f718..cfc301b 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -67,6 +67,26 @@
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 e62c127..ba60a7d 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -62,6 +62,16 @@
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
prop_name: "ro.surface_flinger.max_virtual_display_dimension"