sde: Add support for custom framebuffer sizes
Set a custom framebuffer size for use cases such as panel
simulation. The framebuffer size is defined as the rendering
size or, alternatively, the size of the framebuffer target layer.
Change-Id: Idb30d16383ce334f4ffd629d48be1d3733d4bd16
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index c041e1a..651dd88 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -97,7 +97,7 @@
float y_dpi; //!< Dots per inch in Y-direction.
float fps; //!< Frame rate per second.
uint32_t vsync_period_ns; //!< VSync period in nanoseconds.
- uint32_t v_total; //!< Total lines in Y-direction (vActive + vFP + vBP + vPulseWidth).
+ uint32_t v_total; //!< Total height of panel (vActive + vFP + vBP + vPulseWidth).
uint32_t h_total; //!< Total width of panel (hActive + hFP + hBP + hPulseWidth).
DisplayConfigVariableInfo() : x_pixels(0), y_pixels(0), x_dpi(0.0f), y_dpi(0.0f),
@@ -334,6 +334,13 @@
*/
virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
+ /*! @brief Method to determine whether scaling for a custom resolution is valid.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) = 0;
+
protected:
virtual ~DisplayInterface() { }
};
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 82f7b8d..7dbb6b1 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -351,5 +351,10 @@
SCOPE_LOCK(locker_);
}
+DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) {
+ return res_mgr_.ValidateScaling(crop, dst, rotate90);
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index ae638e0..dd18a7f 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -49,6 +49,7 @@
bool ProcessIdleTimeout(Handle display_ctx);
void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+ DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
// DumpImpl method
virtual void AppendDump(char *buffer, uint32_t length);
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 47beac0..b65b8a5 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -407,6 +407,11 @@
return kErrorNotSupported;
}
+DisplayError DisplayBase::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) {
+ return comp_manager_->ValidateScaling(crop, dst, rotate90);
+}
+
void DisplayBase::AppendDump(char *buffer, uint32_t length) {
DumpImpl::AppendString(buffer, length, "\n-----------------------");
DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 0a33011..cd38d8a 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -59,6 +59,7 @@
virtual DisplayError SetActiveConfig(uint32_t index);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
protected:
// DumpImpl method
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 65ea21f..f034719 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -152,6 +152,12 @@
return DisplayBase::SetDisplayMode(mode);
}
+DisplayError DisplayHDMI::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
HWDisplayAttributes *best = &display_attributes_[0];
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index ea1b80c..6543ee3 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -56,6 +56,7 @@
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual void AppendDump(char *buffer, uint32_t length);
private:
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 0fa5d2b..2466b92 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -214,6 +214,12 @@
return error;
}
+DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 1ed28b2..6f1b574 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -56,6 +56,7 @@
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual void AppendDump(char *buffer, uint32_t length);
// Implement the HWEventHandlers
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
index 5480f0e..9e15469 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -152,6 +152,12 @@
return DisplayBase::SetDisplayMode(mode);
}
+DisplayError DisplayVirtual::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
void DisplayVirtual::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index f868612..2a5c324 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -56,6 +56,7 @@
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
+ virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual void AppendDump(char *buffer, uint32_t length);
private:
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 724b720..bf82a75 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -46,7 +46,8 @@
int id)
: core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
- dump_input_layers_(false), swap_interval_zero_(false) {
+ dump_input_layers_(false), swap_interval_zero_(false), framebuffer_config_(NULL),
+ display_paused_(false) {
}
int HWCDisplay::Init() {
@@ -64,6 +65,13 @@
}
}
+ framebuffer_config_ = new DisplayConfigVariableInfo();
+ if (!framebuffer_config_) {
+ DLOGV("Failed to allocate memory for custom framebuffer config.");
+ core_intf_->DestroyDisplay(display_intf_);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -79,6 +87,8 @@
layer_stack_memory_.raw = NULL;
}
+ delete framebuffer_config_;
+
return 0;
}
@@ -150,10 +160,15 @@
DisplayError error = kErrorNone;
DisplayConfigVariableInfo variable_config;
- error = display_intf_->GetConfig(config, &variable_config);
- if (error != kErrorNone) {
- DLOGE("GetConfig variable info failed. Error = %d", error);
- return -EINVAL;
+ uint32_t active_config = UINT32(GetActiveConfig());
+ if (IsFrameBufferScaled() && config == active_config) {
+ variable_config = *framebuffer_config_;
+ } else {
+ error = display_intf_->GetConfig(config, &variable_config);
+ if (error != kErrorNone) {
+ DLOGE("GetConfig variable info failed. Error = %d", error);
+ return -EINVAL;
+ }
}
for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
@@ -368,7 +383,10 @@
}
}
- SetRect(hwc_layer.displayFrame, &layer.dst_rect);
+ hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
+ ScaleDisplayFrame(&scaled_display_frame);
+
+ SetRect(scaled_display_frame, &layer.dst_rect);
SetRect(hwc_layer.sourceCropf, &layer.src_rect);
for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
@@ -810,5 +828,151 @@
}
}
+int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
+ if (x_pixels <= 0 || y_pixels <= 0) {
+ DLOGV("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
+ return -EINVAL;
+ }
+
+ if (framebuffer_config_->x_pixels == x_pixels && framebuffer_config_->y_pixels == y_pixels) {
+ return 0;
+ }
+
+ DisplayConfigVariableInfo active_config;
+ int active_config_index = GetActiveConfig();
+ DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+ if (error != kErrorNone) {
+ DLOGV("GetConfig variable info failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ if (active_config.x_pixels <= 0 || active_config.y_pixels <= 0) {
+ DLOGV("Invalid panel resolution (%dx%d)", active_config.x_pixels, active_config.y_pixels);
+ return -EINVAL;
+ }
+
+ // Create rects to represent the new source and destination crops
+ LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
+ LayerRect dst = LayerRect(0, 0, FLOAT(active_config.x_pixels), FLOAT(active_config.y_pixels));
+ // Set rotate90 to false since this is taken care of during regular composition.
+ bool rotate90 = false;
+ error = display_intf_->IsScalingValid(crop, dst, rotate90);
+ if (error != kErrorNone) {
+ DLOGV("Unsupported resolution: (%dx%d)", x_pixels, y_pixels);
+ return -EINVAL;
+ }
+
+ uint32_t panel_width =
+ UINT32((FLOAT(active_config.x_pixels) * 25.4f) / FLOAT(active_config.x_dpi));
+ uint32_t panel_height =
+ UINT32((FLOAT(active_config.y_pixels) * 25.4f) / FLOAT(active_config.y_dpi));
+ framebuffer_config_->x_pixels = x_pixels;
+ framebuffer_config_->y_pixels = y_pixels;
+ framebuffer_config_->vsync_period_ns = active_config.vsync_period_ns;
+ framebuffer_config_->x_dpi =
+ (FLOAT(framebuffer_config_->x_pixels) * 25.4f) / FLOAT(panel_width);
+ framebuffer_config_->y_dpi =
+ (FLOAT(framebuffer_config_->y_pixels) * 25.4f) / FLOAT(panel_height);
+
+ DLOGI("New framebuffer resolution (%dx%d)", framebuffer_config_->x_pixels,
+ framebuffer_config_->y_pixels);
+
+ return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ *x_pixels = framebuffer_config_->x_pixels;
+ *y_pixels = framebuffer_config_->y_pixels;
+}
+
+void HWCDisplay::ScaleDisplayFrame(hwc_rect_t *display_frame) {
+ if (!IsFrameBufferScaled()) {
+ return;
+ }
+
+ int active_config_index = GetActiveConfig();
+ DisplayConfigVariableInfo active_config;
+ DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+ if (error != kErrorNone) {
+ DLOGE("GetConfig variable info failed. Error = %d", error);
+ return;
+ }
+
+ float custom_x_pixels = FLOAT(framebuffer_config_->x_pixels);
+ float custom_y_pixels = FLOAT(framebuffer_config_->y_pixels);
+ float active_x_pixels = FLOAT(active_config.x_pixels);
+ float active_y_pixels = FLOAT(active_config.y_pixels);
+ float x_pixels_ratio = active_x_pixels / custom_x_pixels;
+ float y_pixels_ratio = active_y_pixels / custom_y_pixels;
+ float layer_width = FLOAT(display_frame->right - display_frame->left);
+ float layer_height = FLOAT(display_frame->bottom - display_frame->top);
+
+ display_frame->left = INT(x_pixels_ratio * FLOAT(display_frame->left));
+ display_frame->top = INT(y_pixels_ratio * FLOAT(display_frame->top));
+ display_frame->right = INT(FLOAT(display_frame->left) + layer_width * x_pixels_ratio);
+ display_frame->bottom = INT(FLOAT(display_frame->top) + layer_height * y_pixels_ratio);
+}
+
+bool HWCDisplay::IsFrameBufferScaled() {
+ if (framebuffer_config_->x_pixels == 0 || framebuffer_config_->y_pixels == 0) {
+ return false;
+ }
+ uint32_t panel_x_pixels = 0;
+ uint32_t panel_y_pixels = 0;
+ GetPanelResolution(&panel_x_pixels, &panel_y_pixels);
+ return (framebuffer_config_->x_pixels != panel_x_pixels) ||
+ (framebuffer_config_->y_pixels != panel_y_pixels);
+}
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+ DisplayConfigVariableInfo active_config;
+ int active_config_index = GetActiveConfig();
+ DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+ if (error != kErrorNone) {
+ DLOGE("GetConfig variable info failed. Error = %d", error);
+ return;
+ }
+ *x_pixels = active_config.x_pixels;
+ *y_pixels = active_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+ int status = 0;
+
+ switch (display_status) {
+ case kDisplayStatusResume:
+ display_paused_ = false;
+ case kDisplayStatusOnline:
+ status = SetPowerMode(HWC_POWER_MODE_NORMAL);
+ break;
+ case kDisplayStatusPause:
+ display_paused_ = true;
+ case kDisplayStatusOffline:
+ status = SetPowerMode(HWC_POWER_MODE_OFF);
+ break;
+ default:
+ DLOGW("Invalid display status %d", display_status);
+ return -EINVAL;
+ }
+
+ return status;
+}
+
+void HWCDisplay::MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list) {
+ for (size_t i = 0 ; i < (content_list->numHwLayers - 1); i++) {
+ hwc_layer_1_t *layer = &content_list->hwLayers[i];
+ layer->compositionType = HWC_OVERLAY;
+ }
+}
+
+void HWCDisplay::CloseAcquireFences(hwc_display_contents_1_t *content_list) {
+ for (size_t i = 0; i < content_list->numHwLayers; i++) {
+ if (content_list->hwLayers[i].acquireFenceFd >= 0) {
+ close(content_list->hwLayers[i].acquireFenceFd);
+ content_list->hwLayers[i].acquireFenceFd = -1;
+ }
+ }
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index d14699f..bcb037f 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -47,8 +47,19 @@
virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual uint32_t GetLastPowerMode();
+ virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
+ virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+ virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+ virtual int SetDisplayStatus(uint32_t display_status);
protected:
+ enum DisplayStatus {
+ kDisplayStatusOffline = 0,
+ kDisplayStatusOnline,
+ kDisplayStatusPause,
+ kDisplayStatusResume,
+ };
+
// Maximum number of layers supported by display engine.
static const uint32_t kMaxLayerCount = 32;
@@ -99,6 +110,10 @@
void DumpInputBuffers(hwc_display_contents_1_t *content_list);
const char *GetHALPixelFormatString(int format);
const char *GetDisplayString();
+ void ScaleDisplayFrame(hwc_rect_t *display_frame);
+ bool IsFrameBufferScaled();
+ void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
+ void CloseAcquireFences(hwc_display_contents_1_t *content_list);
enum {
INPUT_LAYER_DUMP,
@@ -120,6 +135,8 @@
bool dump_input_layers_;
uint32_t last_power_mode_;
bool swap_interval_zero_;
+ DisplayConfigVariableInfo *framebuffer_config_;
+ bool display_paused_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
index 9601e63..acd7948 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -28,7 +28,6 @@
*/
#include <utils/constants.h>
-#include <gralloc_priv.h>
#include <sync/sync.h>
#include "hwc_display_virtual.h"
@@ -71,6 +70,11 @@
int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
+ if (display_paused_) {
+ MarkLayersForGPUBypass(content_list);
+ return status;
+ }
+
status = AllocateLayerStack(content_list);
if (status) {
return status;
@@ -91,6 +95,22 @@
int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
int status = 0;
+ if (display_paused_) {
+ if (content_list->outbufAcquireFenceFd >= 0) {
+ // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
+ // which will make sure the framework waits on it and closes it.
+ content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
+ close(content_list->outbufAcquireFenceFd);
+ content_list->outbufAcquireFenceFd = -1;
+ }
+ CloseAcquireFences(content_list);
+
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
+ }
+ return status;
+ }
status = HWCDisplay::CommitLayerStack(content_list);
if (status) {
@@ -124,13 +144,15 @@
return -EINVAL;
}
- if ((output_handle->width != INT(output_buffer_->width)) ||
- (output_handle->height != INT(output_buffer_->height)) ||
+ int active_width = GetWidth(output_handle);
+ int active_height = GetHeight(output_handle);
+
+ if ((active_width != INT(output_buffer_->width)) ||
+ (active_height!= INT(output_buffer_->height)) ||
(format != output_buffer_->format)) {
DisplayConfigVariableInfo variable_info;
-
- variable_info.x_pixels = output_handle->width;
- variable_info.y_pixels = output_handle->height;
+ variable_info.x_pixels = active_width;
+ variable_info.y_pixels = active_height;
// TODO(user): Need to get the framerate of primary display and update it.
variable_info.fps = 60;
@@ -164,8 +186,8 @@
return -EINVAL;
}
- output_buffer_->width = output_handle->width;
- output_buffer_->height = output_handle->height;
+ output_buffer_->width = GetWidth(output_handle);
+ output_buffer_->height = GetHeight(output_handle);
output_buffer_->flags.secure = 0;
output_buffer_->flags.video = 0;
@@ -234,5 +256,23 @@
DLOGI("output_layer_dump_enable %d", dump_output_layer_);
}
+int HWCDisplayVirtual::GetWidth(const private_handle_t* handle) {
+ MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+ if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ return metadata->bufferDim.sliceWidth;
+ }
+
+ return handle->width;
+}
+
+int HWCDisplayVirtual::GetHeight(const private_handle_t* handle) {
+ MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+ if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ return metadata->bufferDim.sliceHeight;
+ }
+
+ return handle->height;
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 7ac7c22..3042b12 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -25,6 +25,8 @@
#ifndef __HWC_DISPLAY_VIRTUAL_H__
#define __HWC_DISPLAY_VIRTUAL_H__
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
#include "hwc_display.h"
namespace sde {
@@ -42,6 +44,8 @@
private:
int SetOutputBuffer(hwc_display_contents_1_t *content_list);
void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+ int GetWidth(const private_handle_t* handle);
+ int GetHeight(const private_handle_t* handle);
bool dump_output_layer_;
};
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 450565e..f663889 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -28,14 +28,17 @@
*/
#include <core/dump_interface.h>
+#include <core/buffer_allocator.h>
#include <utils/constants.h>
#include <utils/String16.h>
+#include <cutils/properties.h>
#include <hardware_legacy/uevent.h>
#include <sys/resource.h>
#include <sys/prctl.h>
#include <binder/Parcel.h>
#include <QService.h>
-#include <core/buffer_allocator.h>
+#include <gr.h>
+#include <gralloc_priv.h>
#include "hwc_buffer_allocator.h"
#include "hwc_buffer_sync_handler.h"
@@ -153,6 +156,8 @@
return -errno;
}
+ SetFrameBufferResolution(HWC_DISPLAY_PRIMARY, NULL);
+
return 0;
}
@@ -556,6 +561,7 @@
}
if (display_virtual_) {
+ SetFrameBufferResolution(HWC_DISPLAY_VIRTUAL, content_list);
status = display_virtual_->SetActiveConfig(content_list);
}
@@ -618,6 +624,9 @@
case qService::IQService::SET_DISPLAY_MODE:
status = SetDisplayMode(input_parcel);
break;
+ case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
+ status = SetSecondaryDisplayStatus(input_parcel);
+ break;
default:
DLOGW("QService command = %d is not supported", command);
@@ -627,6 +636,27 @@
return status;
}
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
+ uint32_t display_id = UINT32(input_parcel->readInt32());
+ uint32_t display_status = UINT32(input_parcel->readInt32());
+ HWCDisplay *display = NULL;
+
+ DLOGI("Display %d Status %d", display_id, display_status);
+ switch (display_id) {
+ case HWC_DISPLAY_EXTERNAL:
+ display = display_external_;
+ break;
+ case HWC_DISPLAY_VIRTUAL:
+ display = display_virtual_;
+ break;
+ default:
+ DLOGW("Not supported for display %d", display_id);
+ return -EINVAL;
+ }
+
+ return display->SetDisplayStatus(display_status);
+}
+
android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
DisplayError error = kErrorNone;
uint32_t mode = UINT32(input_parcel->readInt32());
@@ -771,8 +801,9 @@
if (hwc_procs_) {
reset_panel_ = true;
hwc_procs_->invalidate(hwc_procs_);
- } else
+ } else {
DLOGW("Ignore resetpanel - hwc_proc not registered");
+ }
}
}
}
@@ -800,19 +831,19 @@
DLOGI("Powering off primary");
status = display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
if (status) {
- DLOGE("power-off on primary failed with error = %d",status);
+ DLOGE("power-off on primary failed with error = %d", status);
}
DLOGI("Restoring power mode on primary");
uint32_t mode = display_primary_->GetLastPowerMode();
status = display_primary_->SetPowerMode(mode);
if (status) {
- DLOGE("Setting power mode = %d on primary failed with error = %d", mode,status);
+ DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
}
status = display_primary_->EventControl(HWC_EVENT_VSYNC, 1);
if (status) {
- DLOGE("enabling vsync failed for primary with error = %d",status);
+ DLOGE("enabling vsync failed for primary with error = %d", status);
}
reset_panel_ = false;
@@ -849,6 +880,7 @@
display_external_ = NULL;
return -1;
}
+ SetFrameBufferResolution(HWC_DISPLAY_EXTERNAL, NULL);
} else {
SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (!display_external_) {
@@ -868,5 +900,72 @@
return 0;
}
+void HWCSession::SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list) {
+ char property[PROPERTY_VALUE_MAX];
+ uint32_t primary_width = 0;
+ uint32_t primary_height = 0;
+
+ switch (disp) {
+ case HWC_DISPLAY_PRIMARY:
+ {
+ display_primary_->GetPanelResolution(&primary_width, &primary_height);
+ if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
+ char *yptr = strcasestr(property, "x");
+ primary_width = atoi(property);
+ primary_height = atoi(yptr + 1);
+ }
+ display_primary_->SetFrameBufferResolution(primary_width, primary_height);
+ break;
+ }
+
+ case HWC_DISPLAY_EXTERNAL:
+ {
+ uint32_t external_width = 0;
+ uint32_t external_height = 0;
+ display_external_->GetPanelResolution(&external_width, &external_height);
+
+ if (property_get("sys.hwc.mdp_downscale_enabled", property, "false") &&
+ !strcmp(property, "true")) {
+ display_primary_->GetFrameBufferResolution(&primary_width, &primary_height);
+ uint32_t primary_area = primary_width * primary_height;
+ uint32_t external_area = external_width * external_height;
+
+ if (primary_area > external_area) {
+ if (primary_height > primary_width) {
+ Swap(primary_height, primary_width);
+ }
+ AdjustSourceResolution(primary_width, primary_height,
+ &external_width, &external_height);
+ }
+ }
+ display_external_->SetFrameBufferResolution(external_width, external_height);
+ break;
+ }
+
+ case HWC_DISPLAY_VIRTUAL:
+ {
+ if (ValidateContentList(content_list)) {
+ const private_handle_t *output_handle =
+ static_cast<const private_handle_t *>(content_list->outbuf);
+ int virtual_width = 0;
+ int virtual_height = 0;
+ getBufferSizeAndDimensions(output_handle->width, output_handle->height, output_handle->format,
+ virtual_width, virtual_height);
+ display_virtual_->SetFrameBufferResolution(virtual_width, virtual_height);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void HWCSession::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;
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 54ab852..9d5e3d5 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -90,6 +90,10 @@
void SetFrameDumpConfig(const android::Parcel *input_parcel);
android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
android::status_t SetDisplayMode(const android::Parcel *input_parcel);
+ android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
+ void SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list);
+ void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
+ uint32_t *src_width, uint32_t *src_height);
static Locker locker_;
CoreInterface *core_intf_;