sf: Fix virtual display related issues.
1. SurfaceFlinger: Fix virtual display related issues. 1) Validate
output
buffer usage bit appropriately Validate output buffer usage bit only
against GRALLOC_USAGE_HW_COMPOSER to differentiate GLES only
conposition
and HWC/MIXED composition. 2) Exclude video encoder usage for
scratch
buffer Sink and Scratch buffers in VDS are using same usage
flags. This
causes video encoder flag to be set for scratch buffers
Also. Exclude
video encoder flag from scratch buffer usage flags as
scratch buffers
are used only as write back input and not video
encoder input.
2. sf: Allow VDS to use HWC -- Preserve VDS layer
pixel format based on
GRALLOC flags. -- skip color layer for vds
3. sf: Add secure content support for VDS
4. sf: Enable GPU comp. for non-primary displays
Ensure that "Return
status" of dequeueBuffer() complies with API
requirements. Client relies
on this status to call requestBuffer()
upon reallocation.
5. sf: Enable UBWC on virtual display scratch buffer Set
GRALLOC_USAGE_HW_FB usage flag on virtual display Scratch
buffer to
enable UBWC.
Change-Id: Ia49a175372ca187a295531e18f8e84dc22a19486
CRs-Fixed: 2656027
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 1b6c598..2aa20d1 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -109,6 +109,7 @@
"android.hardware.graphics.composer@2.3-command-buffer",
"android.hardware.graphics.composer@2.4-command-buffer",
"android.hardware.graphics.composer3-command-buffer",
+ "display_intf_headers",
],
export_static_lib_headers: [
"libcompositionengine",
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 4b5a68c..2d0d2b3 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -50,7 +50,7 @@
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
- const std::string& name)
+ const std::string& name, bool secure)
: ConsumerBase(bqConsumer),
mHwc(hwc),
mDisplayId(displayId),
@@ -69,7 +69,9 @@
mOutputFence(Fence::NO_FENCE),
mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
+ mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv),
+ mSecure(secure),
+ mSinkUsage(0) {
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bqProducer;
@@ -87,6 +89,8 @@
// on usage bits.
int sinkUsage;
sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
+ mSinkUsage |= (GRALLOC_USAGE_HW_COMPOSER | sinkUsage);
+ setOutputUsage(mSinkUsage);
if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
int sinkFormat;
sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
@@ -119,7 +123,11 @@
}
mMustRecompose = mustRecompose;
-
+ //For WFD use cases we must always set the recompose flag in order
+ //to support pause/resume functionality
+ if (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+ mMustRecompose = true;
+ }
VDS_LOGW_IF(mDebugState != DebugState::Idle, "Unexpected %s in %s state", __func__,
ftl::enum_string(mDebugState).c_str());
mDebugState = DebugState::Begun;
@@ -156,7 +164,7 @@
}
if (mCompositionType != CompositionType::Gpu &&
- (mOutputFormat != mDefaultOutputFormat || mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
+ (mOutputFormat != mDefaultOutputFormat || !(mOutputUsage & GRALLOC_USAGE_HW_COMPOSER))) {
// We must have just switched from GPU-only to MIXED or HWC
// composition. Stop using the format and usage requested by the GPU
// driver; they may be suboptimal when HWC is writing to the output
@@ -168,7 +176,7 @@
// format/usage and get a new buffer when the GPU driver calls
// dequeueBuffer().
mOutputFormat = mDefaultOutputFormat;
- mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
+ setOutputUsage(GRALLOC_USAGE_HW_COMPOSER);
refreshOutputBuffer();
}
@@ -254,7 +262,7 @@
int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
QueueBufferOutput qbo;
VDS_LOGV("%s: queue sink sslot=%d", __func__, sslot);
- if (mMustRecompose) {
+ if (retireFence->isValid() && mMustRecompose) {
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
QueueBufferInput(
systemTime(), false /* isAutoTimestamp */,
@@ -318,6 +326,14 @@
PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
+ // Exclude video encoder usage flag from scratch buffer usage flags.
+ if (source == SOURCE_SCRATCH) {
+ usage |= GRALLOC_USAGE_HW_FB;
+ usage &= ~(GRALLOC_USAGE_HW_VIDEO_ENCODER);
+ VDS_LOGV("dequeueBuffer(%s): updated scratch buffer usage flags=%#" PRIx64,
+ dbgSourceStr(source), usage);
+ }
+
status_t result =
mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
format, usage, nullptr, nullptr);
@@ -347,11 +363,11 @@
}
}
if (result & BUFFER_NEEDS_REALLOCATION) {
- result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
- if (result < 0) {
+ auto status = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
+ if (status < 0) {
mProducerBuffers[pslot].clear();
mSource[source]->cancelBuffer(*sslot, *fence);
- return result;
+ return status;
}
VDS_LOGV("%s(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64, __func__,
ftl::enum_string(source).c_str(), pslot, mProducerBuffers[pslot].get(),
@@ -412,7 +428,7 @@
__func__, w, h, format, usage, mSinkBufferWidth, mSinkBufferHeight,
buf->getPixelFormat(), buf->getUsage());
mOutputFormat = format;
- mOutputUsage = usage;
+ setOutputUsage(usage);
result = refreshOutputBuffer();
if (result < 0)
return result;
@@ -666,6 +682,21 @@
return type == CompositionType::Unknown ? "Unknown"s : ftl::Flags(type).string();
}
+/* Helper to update the output usage when the display is secure */
+
+void VirtualDisplaySurface::setOutputUsage(uint64_t /*flag*/) {
+
+ mOutputUsage = mSinkUsage;
+ if (mSecure && (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER)) {
+ /*TODO: Currently, the framework can only say whether the display
+ * and its subsequent session are secure or not. However, there is
+ * no mechanism to distinguish the different levels of security.
+ * The current solution assumes WV L3 protection.
+ */
+ mOutputUsage |= GRALLOC_USAGE_PROTECTED;
+ }
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 90426f7..805fce9 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -77,7 +77,8 @@
public:
VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
- const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name);
+ const sp<IGraphicBufferConsumer>& bqConsumer,
+ const std::string& name, bool secure);
//
// DisplaySurface interface
@@ -134,6 +135,7 @@
sp<Fence>* outFence, float outTransformMatrix[16]) override;
virtual status_t getUniqueId(uint64_t* outId) const override;
virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
+ virtual void setOutputUsage(uint64_t flag);
//
// Utility methods
@@ -265,6 +267,8 @@
bool mMustRecompose = false;
bool mForceHwcCopy;
+ bool mSecure;
+ int mSinkUsage;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fcead9f..f1e22b3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -163,6 +163,12 @@
#include "Utils/Dumper.h"
#include "WindowInfosListenerInvoker.h"
+#if __has_include("QtiGralloc.h")
+#include "QtiGralloc.h"
+#else
+#include "gralloc_priv.h"
+#endif
+
#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/RenderIntent.h>
@@ -3796,6 +3802,7 @@
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
+ bool canAllocateHwcForVDS = false;
ui::Size resolution(0, 0);
ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
if (state.physical) {
@@ -3810,6 +3817,20 @@
status = state.surface->query(NATIVE_WINDOW_FORMAT, &format);
ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
pixelFormat = static_cast<ui::PixelFormat>(format);
+ if (mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()) {
+ if (maxVirtualDisplaySize == 0 ||
+ ((uint64_t)width <= maxVirtualDisplaySize &&
+ (uint64_t)height <= maxVirtualDisplaySize)) {
+ uint64_t usage = 0;
+ // Replace with native_window_get_consumer_usage ?
+ status = state .surface->getConsumerUsage(&usage);
+ ALOGW_IF(status != NO_ERROR, "Unable to query usage (%d)", status);
+ if ((status == NO_ERROR) && canAllocateHwcDisplayIdForVDS(usage)) {
+ canAllocateHwcForVDS = true;
+ }
+ }
+ }
+
} else {
// Virtual displays without a surface are dormant:
// they have external state (layer stack, projection,
@@ -3842,7 +3863,8 @@
const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
LOG_FATAL_IF(!displayId);
auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,
- bqProducer, bqConsumer, state.displayName);
+ bqProducer, bqConsumer, state.displayName,
+ state.isSecure);
displaySurface = surface;
producer = std::move(surface);
} else {
@@ -8801,6 +8823,20 @@
} // namespace
+bool SurfaceFlinger::canAllocateHwcDisplayIdForVDS(uint64_t usage) {
+ uint64_t flag_mask_pvt_wfd = ~0;
+ uint64_t flag_mask_hw_video = ~0;
+ char value[PROPERTY_VALUE_MAX] = {};
+ property_get("vendor.display.vds_allow_hwc", value, "0");
+ int allowHwcForVDS = atoi(value);
+ // Reserve hardware acceleration for WFD use-case
+ // GRALLOC_USAGE_PRIVATE_WFD + GRALLOC_USAGE_HW_VIDEO_ENCODER = WFD using HW composer.
+ flag_mask_pvt_wfd = GRALLOC_USAGE_PRIVATE_WFD;
+ flag_mask_hw_video = GRALLOC_USAGE_HW_VIDEO_ENCODER;
+ return (allowHwcForVDS || ((usage & flag_mask_pvt_wfd) &&
+ (usage & flag_mask_hw_video)));
+}
+
status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
const gui::DisplayModeSpecs& specs) {
ATRACE_CALL();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a3534b5..8ccc1ce 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -934,6 +934,8 @@
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
std::vector<sp<LayerFE>>& layerFEs);
+ bool canAllocateHwcDisplayIdForVDS(uint64_t usage);
+
// If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a
// matching ownerUid
void traverseLayersInLayerStack(ui::LayerStack, const int32_t uid,