From ac513c2fde2bd385f26f63848ff72ad85d2a4144 Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 28 Mar 2019 16:57:38 -0700 Subject: [PATCH] Fix NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS handling Fixes: 123541940 Test: CTS HardwareRendererTests#testLotsOfBuffers Change-Id: I5d96e615f552c4faa0e6dcaaaa828c871eaf6c8e --- libs/hwui/renderthread/VulkanSurface.cpp | 19 ++++++++++++++----- libs/hwui/renderthread/VulkanSurface.h | 12 +++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp index 1708d3c0e0936..3fed6b09ede26 100644 --- a/libs/hwui/renderthread/VulkanSurface.cpp +++ b/libs/hwui/renderthread/VulkanSurface.cpp @@ -222,7 +222,17 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode, const SkISize maxSize = SkISize::Make(caps.maxImageExtent.width, caps.maxImageExtent.height); ComputeWindowSizeAndTransform(&windowInfo, minSize, maxSize); - windowInfo.bufferCount = std::max(VulkanSurface::sMaxBufferCount, caps.minImageCount); + int query_value; + int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value); + if (err != 0 || query_value < 0) { + ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, + query_value); + return nullptr; + } + auto min_undequeued_buffers = static_cast(query_value); + + windowInfo.bufferCount = min_undequeued_buffers + + std::max(VulkanSurface::sTargetBufferCount, caps.minImageCount); if (caps.maxImageCount > 0 && windowInfo.bufferCount > caps.maxImageCount) { // Application must settle for fewer images than desired: windowInfo.bufferCount = caps.maxImageCount; @@ -357,10 +367,9 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window return false; } - // Lower layer insists that we have at least two buffers. - err = native_window_set_buffer_count(window, std::max(2, windowInfo.bufferCount)); + err = native_window_set_buffer_count(window, windowInfo.bufferCount); if (err != 0) { - ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%d) failed: %s (%d)", + ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%zu) failed: %s (%d)", windowInfo.bufferCount, strerror(-err), err); return false; } @@ -392,7 +401,7 @@ VulkanSurface::~VulkanSurface() { } void VulkanSurface::releaseBuffers() { - for (uint32_t i = 0; i < VulkanSurface::sMaxBufferCount; i++) { + for (uint32_t i = 0; i < mWindowInfo.bufferCount; i++) { VulkanSurface::NativeBufferInfo& bufferInfo = mNativeBuffers[i]; if (bufferInfo.buffer.get() != nullptr && bufferInfo.dequeued) { diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h index 418d40f8c056e..305483fce2d59 100644 --- a/libs/hwui/renderthread/VulkanSurface.h +++ b/libs/hwui/renderthread/VulkanSurface.h @@ -83,14 +83,19 @@ private: * as private to this class. * */ - static constexpr int sMaxBufferCount = 3; + + // How many buffers we want to be able to use ourselves. We want 1 in active rendering with + // 1 more queued, so 2. This will be added to NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, which is + // how many buffers the consumer needs (eg, 1 for SurfaceFlinger), getting to a typically + // triple-buffered queue as a result. + static constexpr uint32_t sTargetBufferCount = 2; struct WindowInfo { SkISize size; PixelFormat pixelFormat; android_dataspace dataspace; int transform; - int bufferCount; + size_t bufferCount; uint64_t windowUsageFlags; // size of the ANativeWindow if the inverse of transform requires us to swap width/height @@ -111,7 +116,8 @@ private: const SkISize& maxSize); void releaseBuffers(); - NativeBufferInfo mNativeBuffers[VulkanSurface::sMaxBufferCount]; + // TODO: Just use a vector? + NativeBufferInfo mNativeBuffers[android::BufferQueueDefs::NUM_BUFFER_SLOTS]; sp mNativeWindow; WindowInfo mWindowInfo;