summaryrefslogtreecommitdiff
path: root/sdm/libs/hwc2/hwc_display_external.cpp
diff options
context:
space:
mode:
authorNaseer Ahmed <naseer@codeaurora.org>2016-03-12 02:03:48 -0500
committerNaseer Ahmed <naseer@codeaurora.org>2016-04-28 17:42:00 -0400
commitb92e73fc10b5fefa69ef93031a91412527d56971 (patch)
tree50cec063f21015e63dbbf5d502e43ba253059c2c /sdm/libs/hwc2/hwc_display_external.cpp
parentc14b2088b079c637cea23dd97d2f68fd7ed624b8 (diff)
downloaddisplay-b92e73fc10b5fefa69ef93031a91412527d56971.tar.gz
hwc: HWC 2.0 implementation
Add HWCLayer, HWCCallbacks and implement HWC2 layer functionality. Change-Id: Ic7764e72f4cae534e68764df4cf80eb3db982071
Diffstat (limited to 'sdm/libs/hwc2/hwc_display_external.cpp')
-rw-r--r--sdm/libs/hwc2/hwc_display_external.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
new file mode 100644
index 00000000..73ed0e8c
--- /dev/null
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -0,0 +1,206 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. 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.
+*/
+
+#include <cutils/properties.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "hwc_display_external.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternal"
+
+namespace sdm {
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCCallbacks *callbacks,
+ qService::QService *qservice, HWCDisplay **hwc_display) {
+ return Create(core_intf, callbacks, 0, 0, qservice, false, hwc_display);
+}
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCCallbacks *callbacks,
+ uint32_t primary_width, uint32_t primary_height,
+ qService::QService *qservice, bool use_primary_res,
+ HWCDisplay **hwc_display) {
+ uint32_t external_width = 0;
+ uint32_t external_height = 0;
+
+ HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, callbacks, qservice);
+ int status = hwc_display_external->Init();
+ if (status) {
+ delete hwc_display_external;
+ return status;
+ }
+
+ hwc_display_external->GetPanelResolution(&external_width, &external_height);
+
+ if (primary_width && primary_height) {
+ // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+ // provided primary_width and primary_height
+ if (use_primary_res) {
+ external_width = primary_width;
+ external_height = primary_height;
+ } else {
+ int downscale_enabled = 0;
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
+ if (downscale_enabled) {
+ GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+ }
+ }
+ }
+
+ status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+ if (status) {
+ Destroy(hwc_display_external);
+ return status;
+ }
+
+ *hwc_display = hwc_display_external;
+
+ return status;
+}
+
+void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+ hwc_display->Deinit();
+ delete hwc_display;
+}
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, HWCCallbacks *callbacks,
+ qService::QService *qservice)
+ : HWCDisplay(core_intf, callbacks, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+ DISPLAY_CLASS_EXTERNAL) {
+}
+
+HWC2::Error HWCDisplayExternal::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ auto status = HWC2::Error::None;
+
+ if (secure_display_active_) {
+ MarkLayersForGPUBypass();
+ return status;
+ }
+
+ BuildLayerStack();
+
+ if (layer_set_.empty()) {
+ flush_ = true;
+ return status;
+ }
+
+ status = PrepareLayerStack(out_num_types, out_num_requests);
+ return status;
+}
+
+HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+
+ if (!secure_display_active_) {
+ status = HWCDisplay::CommitLayerStack();
+ if (status == HWC2::Error::None) {
+ status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ }
+ }
+ CloseAcquireFds();
+ return status;
+}
+
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+ if (display_intf_->IsUnderscanSupported()) {
+ return;
+ }
+
+ // Read user defined width and height ratio
+ int width = 0, height = 0;
+ HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
+ float width_ratio = FLOAT(width) / 100.0f;
+ HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
+ float height_ratio = FLOAT(height) / 100.0f;
+
+ if (width_ratio == 0.0f || height_ratio == 0.0f) {
+ return;
+ }
+
+ uint32_t panel_width = 0;
+ uint32_t panel_height = 0;
+ GetPanelResolution(&panel_width, &panel_height);
+
+ if (panel_width == 0 || panel_height == 0) {
+ DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
+ return;
+ }
+
+ uint32_t new_panel_width = UINT32(panel_width * FLOAT(1.0f - width_ratio));
+ uint32_t new_panel_height = UINT32(panel_height * FLOAT(1.0f - height_ratio));
+
+ int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
+ int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
+
+ display_frame->left =
+ (display_frame->left * INT32(new_panel_width) / INT32(panel_width)) + x_offset;
+ display_frame->top =
+ (display_frame->top * INT32(new_panel_height) / INT32(panel_height)) + y_offset;
+ display_frame->right =
+ ((display_frame->right * INT32(new_panel_width)) / INT32(panel_width)) + x_offset;
+ display_frame->bottom =
+ ((display_frame->bottom * INT32(new_panel_height)) / INT32(panel_height)) + y_offset;
+}
+
+void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active) {
+ if (secure_display_active_ != secure_display_active) {
+ secure_display_active_ = secure_display_active;
+
+ if (secure_display_active_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ }
+ }
+ return;
+}
+
+static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
+ uint32_t *src_height) {
+ *src_height = (dst_width * (*src_height)) / (*src_width);
+ *src_width = dst_width;
+}
+
+void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+ uint32_t *non_primary_width,
+ uint32_t *non_primary_height) {
+ uint32_t primary_area = primary_width * primary_height;
+ uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
+
+ if (primary_area > non_primary_area) {
+ if (primary_height > primary_width) {
+ Swap(primary_height, primary_width);
+ }
+ AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+ }
+}
+
+} // namespace sdm