sdm: hwc2: Enable SolidFill
- Add support for solid fill in hwc2.
- Replace HWCLayers with solid fill layer when
solid fill is enabled.
Bug: 27346522
Crs-fixed: 1012675
Acked-by: Arun Kumar K.R <akumarkr@codeaurora.org>
Change-Id: I0b7e5d3b4417016998e43844cf61e0d967528f63
diff --git a/msm8996/sdm/libs/hwc2/hwc_color_manager.cpp b/msm8996/sdm/libs/hwc2/hwc_color_manager.cpp
index 3075cbb..c40ec4b 100644
--- a/msm8996/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/msm8996/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -166,158 +166,8 @@
return ret;
}
-bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
- HWCDisplay *hwc_display) {
- SCOPE_LOCK(locker_);
-
- // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
- uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
- hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
-
- if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
- // 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
- solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
-
- // 2. continue the prepare<> on solid_fill_layers.
- hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
- // TODO(user): Remove the display_contents generated here and
- // use the solid fill layer support in HWC2 to set this up
- // hwc_display->Prepare(solid_fill_layers_); // RECT info included.
-
- // 3. Set HWC_OVERLAY to all SF layers before returning to framework.
- for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
- hwc_layer_1_t *layer = &layer_list->hwLayers[i];
- layer->compositionType = HWC_OVERLAY;
- }
-
- return true;
- } else if (!solid_fill_enable_) {
- hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
- }
-
- return false;
-}
-
-bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
- HWCDisplay *hwc_display) {
- // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
- SCOPE_LOCK(locker_);
- hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
- if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
- // TODO(user): Present solid fill
- // hwc_display->Commit(solid_fill_layers_);
-
- // SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
- // Close acquire fence fds associated with SF layer stack
- // Close release/retire fence fds returned along with local layer stack
- for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
- int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
- if (fence_fd >= 0) {
- close(fence_fd);
- fence_fd = -1;
- }
- }
-
- for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
- int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
- if (fence_fd >= 0) {
- close(fence_fd);
- fence_fd = -1;
- }
- }
- if (solid_fill_layers_->retireFenceFd >= 0) {
- close(solid_fill_layers_->retireFenceFd);
- solid_fill_layers_->retireFenceFd = -1;
- }
-
- return true;
- }
-
- return false;
-}
-
-int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
- int ret = 0;
-
- if (!solid_fill_layers_) {
- uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
- uint32_t primary_width = 0;
- uint32_t primary_height = 0;
-
- hwc_display->GetMixerResolution(&primary_width, &primary_height);
- uint8_t *buf = new uint8_t[size]();
- // handle for solid fill layer with fd = -1.
- private_handle_t *handle = new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
- BUFFER_TYPE_UI, HAL_PIXEL_FORMAT_RGBA_8888,
- INT32(primary_width), INT32(primary_height));
-
- if (!buf || !handle) {
- DLOGE("Failed to allocate memory.");
- if (buf)
- delete[] buf;
- if (handle)
- delete handle;
-
- return -ENOMEM;
- }
-
- solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
- hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
- layer.handle = handle;
- }
-
- solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
- solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
- solid_fill_layers_->retireFenceFd = -1;
- solid_fill_layers_->outbuf = NULL;
- solid_fill_layers_->outbufAcquireFenceFd = -1;
-
- hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
- hwc_rect_t solid_fill_rect = {
- INT(solid_fill_params_.rect.x), INT(solid_fill_params_.rect.y),
- solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
- solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
- };
-
- layer.compositionType = HWC_FRAMEBUFFER;
- layer.blending = HWC_BLENDING_PREMULT;
- layer.sourceCropf.left = solid_fill_params_.rect.x;
- layer.sourceCropf.top = solid_fill_params_.rect.y;
- layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
- layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
- layer.acquireFenceFd = -1;
- layer.releaseFenceFd = -1;
- layer.flags = 0;
- layer.transform = 0;
- layer.hints = 0;
- layer.planeAlpha = 0xff;
- layer.displayFrame = solid_fill_rect;
- layer.visibleRegionScreen.numRects = 1;
- layer.visibleRegionScreen.rects = &layer.displayFrame;
- layer.surfaceDamage.numRects = 0;
-
- return ret;
-}
-
-void HWCColorManager::DestroySolidFillLayers() {
- if (solid_fill_layers_) {
- hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
- uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
- private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
-
- if (hnd)
- delete hnd;
-
- if (buf)
- delete[] buf;
-
- solid_fill_layers_ = NULL;
- }
-}
-
int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
SCOPE_LOCK(locker_);
- int ret = 0;
if (params) {
solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
@@ -325,15 +175,21 @@
solid_fill_params_ = PPColorFillParams();
}
+ uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
if (enable) {
- // will create solid fill layers for rendering if not present.
- ret = CreateSolidFillLayers(hwc_display);
- } else {
- DestroySolidFillLayers();
- }
- solid_fill_enable_ = enable;
+ LayerRect solid_fill_rect = {
+ FLOAT(solid_fill_params_.rect.x), FLOAT(solid_fill_params_.rect.y),
+ FLOAT(solid_fill_params_.rect.x) + FLOAT(solid_fill_params_.rect.width),
+ FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height),
+ };
- return ret;
+ hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
+ hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
+ } else {
+ hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
+ }
+
+ return 0;
}
int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
diff --git a/msm8996/sdm/libs/hwc2/hwc_color_manager.h b/msm8996/sdm/libs/hwc2/hwc_color_manager.h
new file mode 100644
index 0000000..130dca9
--- /dev/null
+++ b/msm8996/sdm/libs/hwc2/hwc_color_manager.h
@@ -0,0 +1,141 @@
+/* Copyright (c) 2015-2016, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __HWC_COLOR_MANAGER_H__
+#define __HWC_COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <binder/Parcel.h>
+#include <powermanager/IPowerManager.h>
+#include <binder/BinderService.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+
+namespace sdm {
+
+// This macro defines name for display APIs interface wrapper library.
+// This macro shall be used to load library using dlopen().
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-apis.so"
+
+// This macro defines variable name of display color APIs function tables
+// This macro shall be used to specify name of the variable in dlsym().
+#define DISPLAY_API_FUNC_TABLES "display_color_apis_ftables"
+#define QDCM_DIAG_CLIENT_LIBRARY_NAME "libsdm-diag.so"
+#define INIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagInit"
+#define DEINIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagDeInit"
+
+typedef int (*QDCMDiagInit)(void *ftables);
+
+typedef int (*QDCMDiagDeInit)(void);
+
+// Class to encapsulte all details of managing QDCM operating mode.
+class HWCQDCMModeManager {
+ public:
+ static const uint32_t kSocketCMDMaxLength = 4096;
+ static const uint32_t kFullWakeLock = 0x0000001a;
+ static const uint32_t kAcquireCauseWakeup = 0x10000000;
+ static const uint32_t kONAfterRelease = 0x20000000;
+ enum ActiveFeatureID {
+ kCABLFeature,
+ kADFeature,
+ kSVIFeature,
+ kMaxNumActiveFeature,
+ };
+
+ struct ActiveFeatureCMD {
+ const char *cmd_on = NULL;
+ const char *cmd_off = NULL;
+ const char *cmd_query_status = NULL;
+ const char *running = NULL;
+ ActiveFeatureCMD(const char *arg1, const char *arg2, const char *arg3, const char *arg4)
+ : cmd_on(arg1), cmd_off(arg2), cmd_query_status(arg3), running(arg4) {}
+ };
+
+ static const ActiveFeatureCMD kActiveFeatureCMD[kMaxNumActiveFeature];
+
+ public:
+ static HWCQDCMModeManager *CreateQDCMModeMgr();
+ ~HWCQDCMModeManager();
+ int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+
+ protected:
+ bool SendSocketCmd();
+ int AcquireAndroidWakeLock(bool enable);
+ int EnableActiveFeatures(bool enable);
+ int EnableActiveFeatures(bool enable, const ActiveFeatureCMD &cmds, bool *was_running);
+
+ private:
+ bool cabl_was_running_ = false;
+ int socket_fd_ = -1;
+ android::sp<android::IBinder> wakelock_token_ = NULL;
+ android::sp<android::IPowerManager> power_mgr_ = NULL;
+ uint32_t entry_timeout_ = 0;
+ static const char *const kSocketName;
+ static const char *const kTagName;
+ static const char *const kPackageName;
+};
+
+// Class to encapsulte all HWC/OS specific behaviours for ColorManager.
+class HWCColorManager {
+ public:
+ static const int kNumSolidFillLayers = 2;
+ static HWCColorManager *CreateColorManager();
+ static int CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+ PPDisplayAPIPayload *sink);
+ static void MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+ android::Parcel *out_parcel);
+
+ ~HWCColorManager();
+ void DestroyColorManager();
+ int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+ int SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display);
+ int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+
+ protected:
+ int CreateSolidFillLayers(HWCDisplay *hwc_display);
+ void DestroySolidFillLayers();
+ static uint32_t Get8BitsARGBColorValue(const PPColorFillParams ¶ms);
+
+ private:
+ DynLib color_apis_lib_;
+ DynLib diag_client_lib_;
+ void *color_apis_ = NULL;
+ QDCMDiagInit qdcm_diag_init_ = NULL;
+ QDCMDiagDeInit qdcm_diag_deinit_ = NULL;
+ HWCQDCMModeManager *qdcm_mode_mgr_ = NULL;
+
+ PPColorFillParams solid_fill_params_;
+ HWCBufferAllocator *buffer_allocator_ = NULL;
+ BufferInfo buffer_info;
+ Locker locker_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_COLOR_MANAGER_H__
diff --git a/msm8996/sdm/libs/hwc2/hwc_display.cpp b/msm8996/sdm/libs/hwc2/hwc_display.cpp
index edd5bf2..4836289 100644
--- a/msm8996/sdm/libs/hwc2/hwc_display.cpp
+++ b/msm8996/sdm/libs/hwc2/hwc_display.cpp
@@ -389,6 +389,16 @@
layer_stack_.layers.push_back(client_target_->GetSDMLayer());
}
+void HWCDisplay::BuildSolidFillStack() {
+ layer_stack_ = LayerStack();
+ display_rect_ = LayerRect();
+
+ layer_stack_.layers.push_back(solid_fill_layer_);
+ layer_stack_.flags.geometry_changed = 1U;
+ // Append client target to the layer stack
+ layer_stack_.layers.push_back(client_target_->GetSDMLayer());
+}
+
HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
const auto map_layer = layer_map_.find(layer_id);
if (map_layer == layer_map_.end()) {
@@ -1419,6 +1429,68 @@
return ret;
}
+void HWCDisplay::SolidFillPrepare() {
+ if (solid_fill_enable_) {
+ if (solid_fill_layer_ == NULL) {
+ // Create a dummy layer here
+ solid_fill_layer_ = new Layer();
+ solid_fill_layer_->input_buffer = new LayerBuffer();
+ }
+ uint32_t primary_width = 0, primary_height = 0;
+ GetMixerResolution(&primary_width, &primary_height);
+
+ LayerBuffer *layer_buffer = solid_fill_layer_->input_buffer;
+ layer_buffer->width = primary_width;
+ layer_buffer->height = primary_height;
+ layer_buffer->acquire_fence_fd = -1;
+ layer_buffer->release_fence_fd = -1;
+
+ LayerRect rect;
+ rect.top = 0; rect.left = 0;
+ rect.right = primary_width;
+ rect.bottom = primary_height;
+
+ solid_fill_layer_->composition = kCompositionGPU;
+ solid_fill_layer_->src_rect = rect;
+ solid_fill_layer_->dst_rect = rect;
+
+ solid_fill_layer_->blending = kBlendingPremultiplied;
+ solid_fill_layer_->solid_fill_color = solid_fill_color_;
+ solid_fill_layer_->frame_rate = 60;
+ solid_fill_layer_->visible_regions.push_back(solid_fill_layer_->dst_rect);
+ solid_fill_layer_->flags.updating = 1;
+ solid_fill_layer_->flags.solid_fill = true;
+ } else {
+ // delete the dummy layer
+ if (solid_fill_layer_) {
+ delete solid_fill_layer_->input_buffer;
+ }
+ delete solid_fill_layer_;
+ solid_fill_layer_ = NULL;
+ }
+
+ if (solid_fill_enable_ && solid_fill_layer_) {
+ BuildSolidFillStack();
+ MarkLayersForGPUBypass();
+ }
+
+ return;
+}
+
+void HWCDisplay::SolidFillCommit() {
+ if (solid_fill_enable_ && solid_fill_layer_) {
+ LayerBuffer *layer_buffer = solid_fill_layer_->input_buffer;
+ if (layer_buffer->release_fence_fd > 0) {
+ close(layer_buffer->release_fence_fd);
+ layer_buffer->release_fence_fd = -1;
+ }
+ if (layer_stack_.retire_fence_fd > 0) {
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ }
+ }
+}
+
int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
if (!IsValid(display_rect_)) {
return -EINVAL;
@@ -1459,7 +1531,7 @@
bool HWCDisplay::SingleLayerUpdating(void) {
uint32_t updating_count = 0;
- for (uint i = 0; i < layer_set_.size(); i++) {
+ for (uint i = 0; i < layer_stack_.layers.size(); i++) {
auto layer = layer_stack_.layers.at(i);
if (layer->flags.updating) {
updating_count++;
diff --git a/msm8996/sdm/libs/hwc2/hwc_display.h b/msm8996/sdm/libs/hwc2/hwc_display.h
index 277514d..880fca2 100644
--- a/msm8996/sdm/libs/hwc2/hwc_display.h
+++ b/msm8996/sdm/libs/hwc2/hwc_display.h
@@ -130,9 +130,12 @@
int ToggleScreenUpdates(bool enable);
int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload, PPDisplayAPIPayload *out_payload,
PPPendingParams *pending_action);
+ void SolidFillPrepare();
+ void SolidFillCommit();
DisplayClass GetDisplayClass();
int GetVisibleDisplayRect(hwc_rect_t *rect);
void BuildLayerStack(void);
+ void BuildSolidFillStack(void);
HWCLayer *GetHWCLayer(hwc2_layer_t layer);
// HWC2 APIs
@@ -249,6 +252,8 @@
bool secure_display_active_ = false;
bool skip_prepare_ = false;
bool solid_fill_enable_ = false;
+ Layer *solid_fill_layer_ = NULL;
+ LayerRect solid_fill_rect_ = {};
uint32_t solid_fill_color_ = 0;
LayerRect display_rect_;
bool validated_ = false;
diff --git a/msm8996/sdm/libs/hwc2/hwc_display_primary.cpp b/msm8996/sdm/libs/hwc2/hwc_display_primary.cpp
index 56ff335..7dac376 100644
--- a/msm8996/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/msm8996/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -174,6 +174,8 @@
// Fill in the remaining blanks in the layers and add them to the SDM layerstack
BuildLayerStack();
+ // Checks and replaces layer stack for solid fill
+ SolidFillPrepare();
bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
@@ -224,9 +226,11 @@
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
HandleFrameOutput();
+ SolidFillCommit();
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
}
+
CloseAcquireFds();
return status;
}
@@ -276,28 +280,40 @@
int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
va_list args;
va_start(args, operation);
- int val = va_arg(args, int32_t);
- va_end(args);
+ int val = 0;
+ LayerRect *rect = NULL;
+
switch (operation) {
case SET_METADATA_DYN_REFRESH_RATE:
+ val = va_arg(args, int32_t);
SetMetaDataRefreshRateFlag(val);
break;
case SET_BINDER_DYN_REFRESH_RATE:
+ val = va_arg(args, int32_t);
ForceRefreshRate(UINT32(val));
break;
case SET_DISPLAY_MODE:
+ val = va_arg(args, int32_t);
SetDisplayMode(UINT32(val));
break;
case SET_QDCM_SOLID_FILL_INFO:
+ val = va_arg(args, int32_t);
SetQDCMSolidFillInfo(true, UINT32(val));
break;
case UNSET_QDCM_SOLID_FILL_INFO:
+ val = va_arg(args, int32_t);
SetQDCMSolidFillInfo(false, UINT32(val));
break;
+ case SET_QDCM_SOLID_FILL_RECT:
+ rect = va_arg(args, LayerRect*);
+ solid_fill_rect_ = *rect;
+ break;
default:
DLOGW("Invalid operation %d", operation);
+ va_end(args);
return -EINVAL;
}
+ va_end(args);
return 0;
}
diff --git a/msm8996/sdm/libs/hwc2/hwc_display_primary.h b/msm8996/sdm/libs/hwc2/hwc_display_primary.h
index 32d265e..ab46cde 100644
--- a/msm8996/sdm/libs/hwc2/hwc_display_primary.h
+++ b/msm8996/sdm/libs/hwc2/hwc_display_primary.h
@@ -45,6 +45,7 @@
SET_DISPLAY_MODE,
SET_QDCM_SOLID_FILL_INFO,
UNSET_QDCM_SOLID_FILL_INFO,
+ SET_QDCM_SOLID_FILL_RECT,
};
static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/msm8996/sdm/libs/hwc2/hwc_session.cpp b/msm8996/sdm/libs/hwc2/hwc_session.cpp
index 224b17e..df24098 100644
--- a/msm8996/sdm/libs/hwc2/hwc_session.cpp
+++ b/msm8996/sdm/libs/hwc2/hwc_session.cpp
@@ -387,10 +387,9 @@
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
- // TODO(user): Handle solid fill layers
+
auto status = HWC2::Error::BadDisplay;
// TODO(user): Handle virtual display/HDMI concurrency
-
if (hwc_session->hwc_display_[display]) {
status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
// This is only indicative of how many times SurfaceFlinger posts