sde: resource manager: multi display support
Move some state info into display ctx.
Reorganize layer config for display split config case.
Add macro tile format check for scaling limit difference.
Change-Id: If9c3bed6161343828c14f784f69269c181510223
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index 5e813ea..c069c60 100755
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -108,11 +108,13 @@
@sa LayerBuffer
*/
struct LayerBufferFlags {
- uint64_t secure : 1; //!< This flag shall be set by client to indicate that the buffer need
- //!< to be handled securely.
- uint64_t video : 1; //!< This flag shall be set by client to indicate that the buffer is
- //!< video/ui buffer
- LayerBufferFlags() : secure(0) { }
+ uint64_t secure : 1; //!< This flag shall be set by client to indicate that the buffer need
+ //!< to be handled securely.
+ uint64_t video : 1; //!< This flag shall be set by client to indicate that the buffer is
+ //!< video/ui buffer
+ uint64_t macro_tile : 1; //!< This flag shall be set by client to indicate that the buffer format
+ //!< is macro tiled.
+ LayerBufferFlags() : secure(0), video(0), macro_tile(0) { }
};
/*! @brief This structure defines a layer buffer handle which contains raw buffer and its associated
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 84870b8..bbedc65 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -99,15 +99,17 @@
uint8_t decimation;
HWPipeInfo() : pipe_id(0), decimation(1) { }
+
+ inline void Reset() { *this = HWPipeInfo(); }
};
struct HWLayerConfig {
- bool use_non_dma_pipe;
- bool is_right_pipe;
- HWPipeInfo left_pipe;
- HWPipeInfo right_pipe;
+ bool use_non_dma_pipe; // set by client
+ bool is_right_pipe; // indicate if right pipe is valid
+ HWPipeInfo left_pipe; // pipe for left side of the buffer
+ HWPipeInfo right_pipe; // pipe for right side of the buffer
- HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(true) { }
+ HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(false) { }
};
struct HWLayers {
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
old mode 100755
new mode 100644
index 73ea4a4..d8b8430
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -32,115 +32,200 @@
namespace sde {
-DisplayError ResManager::Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers) {
- HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+DisplayError ResManager::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+ const Layer &layer, const LayerRect &src_rect,
+ const LayerRect &dst_rect,
+ HWLayerConfig *layer_config) {
HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
- HWLayersInfo &layer_info = hw_layers->info;
+ // for display split case
+ HWPipeInfo *left_pipe = &layer_config->left_pipe;
+ HWPipeInfo *right_pipe = &layer_config->right_pipe;
+ LayerRect scissor, dst_left, crop_left, crop_right, dst_right;
+ layer_config->is_right_pipe = false;
+ scissor.right = FLOAT(display_attributes.split_left);
+ scissor.bottom = FLOAT(display_attributes.y_pixels);
- for (uint32_t i = 0; i < layer_info.count; i++) {
- Layer& layer = layer_info.stack->layers[layer_info.index[i]];
- float w_scale, h_scale;
- if (!IsValidDimension(layer, &w_scale, &h_scale)) {
- DLOGV("Invalid dimension");
+ crop_left = src_rect;
+ dst_left = dst_rect;
+ crop_right = crop_left;
+ dst_right = dst_left;
+ LayerTransform transform = layer.transform;
+ CalculateCropRects(scissor, transform, &crop_left, &dst_left);
+ scissor.left = FLOAT(display_attributes.split_left);
+ scissor.top = 0.0f;
+ scissor.right = FLOAT(display_attributes.x_pixels);
+ scissor.bottom = FLOAT(display_attributes.y_pixels);
+ CalculateCropRects(scissor, transform, &crop_right, &dst_right);
+ if ((crop_left.right - crop_left.left) >= kMaxSourcePipeWidth) {
+ if (crop_right.right != crop_right.left)
return kErrorNotSupported;
- }
+ // 2 pipes both are on the left
+ SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
+ &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+ left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ right_pipe->pipe_id = kPipeIdNeedsAssignment;
+ layer_config->is_right_pipe = true;
+ } else if ((crop_right.right - crop_right.left) >= kMaxSourcePipeWidth) {
+ if (crop_left.right != crop_left.left)
+ return kErrorNotSupported;
+ // 2 pipes both are on the right
+ SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
+ &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+ left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ right_pipe->pipe_id = kPipeIdNeedsAssignment;
+ layer_config->is_right_pipe = true;
+ } else if (UINT32(dst_left.right) > UINT32(dst_left.left)) {
+ // assign left pipe
+ left_pipe->src_roi = crop_left;
+ left_pipe->dst_roi = dst_left;
+ left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ } else {
+ // Set default value, left_pipe is not needed.
+ left_pipe->Reset();
+ }
- LayerRect scissor;
- scissor.right = FLOAT(display_attributes.split_left);
- scissor.bottom = FLOAT(display_attributes.y_pixels);
- LayerRect crop = layer.src_rect;
- LayerRect dst = layer.dst_rect;
- LayerRect cropRight = crop;
- LayerRect dstRight = dst;
- CalculateCropRects(&crop, &dst, scissor, layer.transform);
- HWPipeInfo *pipe_info = &hw_layers->config[i].left_pipe;
-
- pipe_info->src_roi = crop;
- pipe_info->dst_roi = dst;
-
- float crop_width = cropRight.right - cropRight.left;
- pipe_info = &hw_layers->config[i].right_pipe;
- if ((dstRight.right - dstRight.left) > kMaxInterfaceWidth ||
- crop_width > kMaxInterfaceWidth ||
- ((hw_block_id == kHWPrimary) &&
- (crop_width > display_attributes.split_left))) {
- scissor.left = FLOAT(display_attributes.split_left);
- scissor.top = 0.0f;
- scissor.right = FLOAT(display_attributes.x_pixels);
- scissor.bottom = FLOAT(display_attributes.y_pixels);
- CalculateCropRects(&cropRight, &dstRight, scissor, layer.transform);
- pipe_info->src_roi = cropRight;
- pipe_info->dst_roi = dstRight;
- pipe_info->pipe_id = -1;
+ // assign right pipe if needed
+ if (UINT32(dst_right.right) > UINT32(dst_right.left)) {
+ if (left_pipe->pipe_id) {
+ right_pipe->src_roi = crop_right;
+ right_pipe->dst_roi = dst_right;
+ right_pipe->pipe_id = kPipeIdNeedsAssignment;
+ layer_config->is_right_pipe = true;
} else {
- // need not right pipe
- pipe_info->pipe_id = 0;
+ // If left pipe is not used, use left pipe first.
+ left_pipe->src_roi = crop_right;
+ left_pipe->dst_roi = dst_right;
+ left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ right_pipe->Reset();
}
+ } else {
+ // need not right pipe
+ right_pipe->Reset();
}
return kErrorNone;
}
-bool ResManager::IsValidDimension(const Layer& layer, float *width_scale, float *height_scale) {
- if (IsNonIntegralSrcCrop(layer.src_rect)) {
- return false;
- }
+DisplayError ResManager::Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers,
+ uint32_t *rotate_count) {
+ HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+ HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+ HWLayersInfo &layer_info = hw_layers->info;
+ DisplayError error = kErrorNone;
- LayerRect crop;
- LayerRect dst;
- IntegerizeRect(&crop, layer.src_rect);
- IntegerizeRect(&dst, layer.dst_rect);
+ for (uint32_t i = 0; i < layer_info.count; i++) {
+ Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+ float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
+ if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
+ DLOGE_IF(kTagResources, "Input is invalid");
+ LogRectVerbose("input layer src_rect", layer.src_rect);
+ LogRectVerbose("input layer dst_rect", layer.dst_rect);
+ return kErrorNotSupported;
+ }
- bool rotated90 = (static_cast<int>(layer.transform.rotation) == 90);
- float crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
- float crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
- float dst_w = dst.right - dst.left;
- float dst_h = dst.bottom - dst.top;
+ LayerRect scissor, src_rect, dst_rect;
+ src_rect = layer.src_rect;
+ dst_rect = layer.dst_rect;
+ scissor.right = FLOAT(display_attributes.x_pixels);
+ scissor.bottom = FLOAT(display_attributes.y_pixels);
+ CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect);
- if ((dst_w < 1) || (dst_h < 1)) {
- return false;
- }
+ if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale_x, &rot_scale_y))
+ return kErrorNotSupported;
- float w_scale = crop_w / dst_w;
- float h_scale = crop_h / dst_h;
+ error = DisplaySplitConfig(display_resource_ctx, layer, src_rect,
+ dst_rect, &hw_layers->config[i]);
+ if (error != kErrorNone)
+ break;
- if ((crop_w < kMaxCropWidth) ||(crop_h < kMaxCropHeight)) {
- return false;
- }
-
- if ((w_scale > 1.0f) || (h_scale > 1.0f)) {
- const uint32_t max_scale_down = hw_res_info_.max_scale_down;
-
- if (!hw_res_info_.has_decimation) {
- if (crop_w > kMaxSourcePipeWidth || w_scale > max_scale_down || h_scale > max_scale_down) {
- return false;
- }
- } else {
- if (w_scale > max_scale_down || h_scale > max_scale_down) {
- return false;
- }
+ DLOGV_IF(kTagResources, "layer = %d, left pipe_id = %x",
+ i, hw_layers->config[i].left_pipe.pipe_id);
+ LogRectVerbose("input layer src_rect", layer.src_rect);
+ LogRectVerbose("input layer dst_rect", layer.dst_rect);
+ LogRectVerbose("cropped src_rect", src_rect);
+ LogRectVerbose("cropped dst_rect", dst_rect);
+ LogRectVerbose("left pipe src", hw_layers->config[i].left_pipe.src_roi);
+ LogRectVerbose("left pipe dst", hw_layers->config[i].left_pipe.dst_roi);
+ if (hw_layers->config[i].right_pipe.pipe_id) {
+ LogRectVerbose("right pipe src", hw_layers->config[i].right_pipe.src_roi);
+ LogRectVerbose("right pipe dst", hw_layers->config[i].right_pipe.dst_roi);
}
}
- if (((w_scale < 1.0f) || (h_scale < 1.0f)) && (w_scale > 0.0f) && (h_scale > 0.0f)) {
- const uint32_t max_scale_up = hw_res_info_.max_scale_up;
- const float w_uscale = 1.0f / w_scale;
- const float h_uscale = 1.0f / h_scale;
-
- if (w_uscale > max_scale_up || h_uscale > max_scale_up) {
- return false;
- }
- }
-
- *width_scale = w_scale;
- *height_scale = h_scale;
-
- return true;
+ return error;
}
-void ResManager::CalculateCut(float *left_cut_ratio,
- float *top_cut_ratio, float *right_cut_ratio, float *bottom_cut_ratio,
- const LayerTransform& transform) {
+DisplayError ResManager::ValidateScaling(const Layer &layer, const LayerRect &crop,
+ const LayerRect &dst, float *rot_scale_x,
+ float *rot_scale_y) {
+ bool rotated90 = (UINT32(layer.transform.rotation) == 90);
+ float crop_width = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
+ float crop_height = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
+ float dst_width = dst.right - dst.left;
+ float dst_height = dst.bottom - dst.top;
+
+ if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
+ DLOGV_IF(kTagResources, "Destination region is too small w = %d, h = %d",
+ dst_width, dst_height);
+ return kErrorNotSupported;
+ }
+
+ if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
+ DLOGV_IF(kTagResources, "source region is too small w = %d, h = %d", crop_width, crop_height);
+ return kErrorNotSupported;
+ }
+
+ float scale_x = crop_width / dst_width;
+ float scale_y = crop_height / dst_height;
+
+ if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+ const uint32_t max_scale_down = hw_res_info_.max_scale_down;
+ if (((!hw_res_info_.has_decimation) || (IsMacroTileFormat(layer.input_buffer))) &&
+ (scale_x > max_scale_down || scale_y > max_scale_down)) {
+ DLOGV_IF(kTagResources,
+ "Scaling down is over the limit is_tile = %d, scale_x = %d, scale_y = %d",
+ IsMacroTileFormat(layer.input_buffer), scale_x, scale_y);
+ return kErrorNotSupported;
+ }
+ }
+
+ const uint32_t max_scale_up = hw_res_info_.max_scale_up;
+ if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+ if ((1.0f / scale_x) > max_scale_up) {
+ DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %d", 1.0f / scale_x);
+ return kErrorNotSupported;
+ }
+ }
+
+ if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+ if ((1.0f / scale_y) > max_scale_up) {
+ DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %d", 1.0f / scale_y);
+ return kErrorNotSupported;
+ }
+ }
+
+ // Calculate rotator downscale ratio
+ float rot_scale = 1.0f;
+ while (scale_x > hw_res_info_.max_scale_down) {
+ scale_x /= 2;
+ rot_scale *= 2;
+ }
+ *rot_scale_x = rot_scale;
+
+ rot_scale = 1.0f;
+ while (scale_y > hw_res_info_.max_scale_down) {
+ scale_y /= 2;
+ rot_scale *= 2;
+ }
+ *rot_scale_y = rot_scale;
+ DLOGV_IF(kTagResources, "rotator scaling hor = %.0f, ver = %.0f", *rot_scale_x, *rot_scale_y);
+
+ return kErrorNone;
+}
+
+void ResManager::CalculateCut(const LayerTransform &transform, float *left_cut_ratio,
+ float *top_cut_ratio, float *right_cut_ratio,
+ float *bottom_cut_ratio) {
if (transform.flip_horizontal) {
Swap(*left_cut_ratio, *right_cut_ratio);
}
@@ -159,75 +244,80 @@
}
}
-void ResManager::CalculateCropRects(LayerRect *crop, LayerRect *dst,
- const LayerRect& scissor, const LayerTransform& transform) {
- float& crop_l = crop->left;
- float& crop_t = crop->top;
- float& crop_r = crop->right;
- float& crop_b = crop->bottom;
- float crop_w = crop->right - crop->left;
- float crop_h = crop->bottom - crop->top;
+void ResManager::CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
+ LayerRect *crop, LayerRect *dst) {
+ float &crop_left = crop->left;
+ float &crop_top = crop->top;
+ float &crop_right = crop->right;
+ float &crop_bottom = crop->bottom;
+ float crop_width = crop->right - crop->left;
+ float crop_height = crop->bottom - crop->top;
- float& dst_l = dst->left;
- float& dst_t = dst->top;
- float& dst_r = dst->right;
- float& dst_b = dst->bottom;
- float dst_w = (dst->right > dst->left) ? dst->right - dst->left :
- dst->left - dst->right;
- float dst_h = (dst->bottom > dst->top) ? dst->bottom > dst->top :
- dst->top > dst->bottom;
+ float &dst_left = dst->left;
+ float &dst_top = dst->top;
+ float &dst_right = dst->right;
+ float &dst_bottom = dst->bottom;
+ float dst_width = dst->right - dst->left;
+ float dst_height = dst->bottom - dst->top;
- const float& sci_l = scissor.left;
- const float& sci_t = scissor.top;
- const float& sci_r = scissor.right;
- const float& sci_b = scissor.bottom;
+ const float &sci_left = scissor.left;
+ const float &sci_top = scissor.top;
+ const float &sci_right = scissor.right;
+ const float &sci_bottom = scissor.bottom;
- float left_cut_ratio = 0.0, right_cut_ratio = 0.0, top_cut_ratio = 0.0,
- bottom_cut_ratio = 0.0;
+ float left_cut_ratio = 0.0, right_cut_ratio = 0.0, top_cut_ratio = 0.0, bottom_cut_ratio = 0.0;
+ bool need_cut = false;
- if (dst_l < sci_l) {
- left_cut_ratio = (sci_l - dst_l) / dst_w;
- dst_l = sci_l;
+ if (dst_left < sci_left) {
+ left_cut_ratio = (sci_left - dst_left) / dst_width;
+ dst_left = sci_left;
+ need_cut = true;
}
- if (dst_r > sci_r) {
- right_cut_ratio = (dst_r - sci_r) / dst_w;
- dst_r = sci_r;
+ if (dst_right > sci_right) {
+ right_cut_ratio = (dst_right - sci_right) / dst_width;
+ dst_right = sci_right;
+ need_cut = true;
}
- if (dst_t < sci_t) {
- top_cut_ratio = (sci_t - dst_t) / (dst_h);
- dst_t = sci_t;
+ if (dst_top < sci_top) {
+ top_cut_ratio = (sci_top - dst_top) / (dst_height);
+ dst_top = sci_top;
+ need_cut = true;
}
- if (dst_b > sci_b) {
- bottom_cut_ratio = (dst_b - sci_b) / (dst_h);
- dst_b = sci_b;
+ if (dst_bottom > sci_bottom) {
+ bottom_cut_ratio = (dst_bottom - sci_bottom) / (dst_height);
+ dst_bottom = sci_bottom;
+ need_cut = true;
}
- CalculateCut(&left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio, transform);
- crop_l += crop_w * left_cut_ratio;
- crop_t += crop_h * top_cut_ratio;
- crop_r -= crop_w * right_cut_ratio;
- crop_b -= crop_h * bottom_cut_ratio;
+ if (!need_cut)
+ return;
+
+ CalculateCut(transform, &left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio);
+ crop_left += crop_width * left_cut_ratio;
+ crop_top += crop_height * top_cut_ratio;
+ crop_right -= crop_width * right_cut_ratio;
+ crop_bottom -= crop_height * bottom_cut_ratio;
}
-bool ResManager::IsNonIntegralSrcCrop(const LayerRect& crop) {
- if (crop.left - roundf(crop.left) ||
- crop.top - roundf(crop.top) ||
- crop.right - roundf(crop.right) ||
- crop.bottom - roundf(crop.bottom)) {
- return true;
- } else {
+bool ResManager::IsValidDimension(const LayerRect &src, const LayerRect &dst) {
+ // Make sure source in integral
+ if (src.left - roundf(src.left) ||
+ src.top - roundf(src.top) ||
+ src.right - roundf(src.right) ||
+ src.bottom - roundf(src.bottom)) {
+ DLOGE_IF(kTagResources, "Input ROI is not integral");
return false;
}
-}
-void ResManager::IntegerizeRect(LayerRect *dst_rect, const LayerRect &src_rect) {
- dst_rect->left = ceilf(src_rect.left);
- dst_rect->top = ceilf(src_rect.top);
- dst_rect->right = floorf(src_rect.right);
- dst_rect->bottom = floorf(src_rect.bottom);
+ if (src.left > src.right || src.top > src.bottom || dst.left > dst.right ||
+ dst.top > dst.bottom) {
+ return false;
+ } else {
+ return true;
+ }
}
void ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
@@ -248,5 +338,58 @@
pipe->decimation = UINT8(powf(2.0f, decimation_factor));
}
-} // namespace sde
+void ResManager::SplitRect(bool flip_horizontal, const LayerRect &src_rect,
+ const LayerRect &dst_rect, LayerRect *src_left, LayerRect *dst_left,
+ LayerRect *src_right, LayerRect *dst_right) {
+ // Split rectangle horizontally and evenly into two.
+ float src_width = src_rect.right - src_rect.left;
+ float dst_width = dst_rect.right - dst_rect.left;
+ if (flip_horizontal) {
+ src_left->top = src_rect.top;
+ src_left->left = src_rect.left;
+ src_left->right = src_rect.left + (src_width / 2);
+ src_left->bottom = src_rect.bottom;
+ dst_left->top = dst_rect.top;
+ dst_left->left = dst_rect.left + (dst_width / 2);
+ dst_left->right = dst_rect.right;
+ dst_left->bottom = dst_rect.bottom;
+
+ src_right->top = src_rect.top;
+ src_right->left = src_left->right;
+ src_right->right = src_rect.right;
+ src_right->bottom = src_rect.bottom;
+
+ dst_right->top = dst_rect.top;
+ dst_right->left = dst_rect.left;
+ dst_right->right = dst_left->left;
+ dst_right->bottom = dst_rect.bottom;
+ } else {
+ src_left->top = src_rect.top;
+ src_left->left = src_rect.left;
+ src_left->right = src_rect.left + (src_width / 2);
+ src_left->bottom = src_rect.bottom;
+
+ dst_left->top = dst_rect.top;
+ dst_left->left = dst_rect.left;
+ dst_left->right = dst_rect.left + (dst_width / 2);
+ dst_left->bottom = dst_rect.bottom;
+
+ src_right->top = src_rect.top;
+ src_right->left = src_left->right;
+ src_right->right = src_rect.right;
+ src_right->bottom = src_rect.bottom;
+
+ dst_right->top = dst_rect.top;
+ dst_right->left = dst_left->right;
+ dst_right->right = dst_rect.right;
+ dst_right->bottom = dst_rect.bottom;
+ }
+}
+
+void ResManager::LogRectVerbose(const char *prefix, const LayerRect &roi) {
+ DLOGV_IF(kTagResources,"%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+ prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+} // namespace sde
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
old mode 100755
new mode 100644
index 1ccb410..7add793
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -32,7 +32,7 @@
namespace sde {
ResManager::ResManager()
- : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), frame_start_(false) {
+ : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0) {
}
DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
@@ -42,7 +42,7 @@
num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
- if (UNLIKELY(num_pipe_ > kPipeIdMax)) {
+ if (num_pipe_ > kPipeIdMax) {
DLOGE("Number of pipe is over the limit! %d", num_pipe_);
return kErrorParameters;
}
@@ -89,28 +89,27 @@
}
DisplayError ResManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- Handle *display_ctx) {
+ Handle *display_ctx) {
DisplayError error = kErrorNone;
HWBlockType hw_block_id = kHWBlockMax;
switch (type) {
case kPrimary:
- if (UNLIKELY(!hw_block_ctx_[kHWPrimary].is_in_use)) {
+ if (!hw_block_ctx_[kHWPrimary].is_in_use) {
hw_block_id = kHWPrimary;
}
break;
case kHDMI:
- if (UNLIKELY(!hw_block_ctx_[kHWHDMI].is_in_use)) {
+ if (!hw_block_ctx_[kHWHDMI].is_in_use) {
hw_block_id = kHWHDMI;
}
break;
case kVirtual:
- // assume only WB2 can be used for vitrual display
- if (UNLIKELY(!hw_block_ctx_[kHWWriteback2].is_in_use)) {
- hw_block_id = kHWWriteback2;
- }
+ // assume only WB2 can be used for virtual display
+ virtual_count_++;
+ hw_block_id = kHWWriteback2;
break;
default:
@@ -118,12 +117,12 @@
return kErrorParameters;
}
- if (UNLIKELY(hw_block_id == kHWBlockMax)) {
+ if (hw_block_id == kHWBlockMax) {
return kErrorResources;
}
DisplayResourceContext *display_resource_ctx = new DisplayResourceContext();
- if (UNLIKELY(!display_resource_ctx)) {
+ if (!display_resource_ctx) {
return kErrorMemory;
}
@@ -132,10 +131,12 @@
display_resource_ctx->display_attributes = attributes;
display_resource_ctx->display_type = type;
display_resource_ctx->hw_block_id = hw_block_id;
+ if (!display_resource_ctx->display_attributes.is_device_split)
+ display_resource_ctx->display_attributes.split_left =
+ display_resource_ctx->display_attributes.x_pixels;
*display_ctx = display_resource_ctx;
-
- return kErrorNone;
+ return error;
}
DisplayError ResManager::UnregisterDisplay(Handle display_ctx) {
@@ -143,25 +144,30 @@
reinterpret_cast<DisplayResourceContext *>(display_ctx);
Purge(display_ctx);
- hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+ if (display_resource_ctx->hw_block_id == kHWWriteback2) {
+ virtual_count_--;
+ if (!virtual_count_)
+ hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+ } else {
+ hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+ }
delete display_resource_ctx;
return kErrorNone;
}
-
DisplayError ResManager::Start(Handle display_ctx) {
locker_.Lock();
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
- if (frame_start_) {
+ if (display_resource_ctx->frame_start) {
return kErrorNone; // keep context locked.
}
// First call in the cycle
- frame_start_ = true;
+ display_resource_ctx->frame_start = true;
display_resource_ctx->frame_count++;
// Release the pipes not used in the previous cycle
@@ -172,6 +178,7 @@
src_pipes_[i].state = kPipeStateIdle;
}
}
+
return kErrorNone;
}
@@ -191,22 +198,25 @@
DisplayError error = kErrorNone;
const struct HWLayersInfo &layer_info = hw_layers->info;
- if (UNLIKELY(layer_info.count > num_pipe_)) {
+ if (layer_info.count > num_pipe_) {
return kErrorResources;
}
- error = Config(display_resource_ctx, hw_layers);
- if (UNLIKELY(error != kErrorNone)) {
+ uint32_t rotate_count = 0;
+ error = Config(display_resource_ctx, hw_layers, &rotate_count);
+ if (error != kErrorNone) {
return error;
}
- uint32_t left_index = 0;
+ uint32_t left_index = kPipeIdMax;
bool need_scale = false;
HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+ HWBlockType rotator_block = kHWBlockMax;
// Clear reserved marking
for (uint32_t i = 0; i < num_pipe_; i++) {
- src_pipes_[i].reserved = false;
+ if (src_pipes_[i].reserved_hw_block == hw_block_id)
+ src_pipes_[i].reserved_hw_block = kHWBlockMax;
}
for (uint32_t i = 0; i < layer_info.count; i++) {
@@ -220,26 +230,28 @@
HWPipeInfo *pipe_info = &hw_layers->config[i].left_pipe;
- need_scale = IsScalingNeeded(pipe_info);
-
// Should have a generic macro
- bool is_yuv = (layer.input_buffer->format >= kFormatYCbCr420Planar);
+ bool is_yuv = IsYuvFormat(layer.input_buffer->format);
- left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
- if (left_index >= num_pipe_) {
- goto Acquire_failed;
+ // left pipe is needed
+ if (pipe_info->pipe_id) {
+ need_scale = IsScalingNeeded(pipe_info);
+ left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
+ if (left_index >= num_pipe_) {
+ goto CleanupOnError;
+ }
+ src_pipes_[left_index].reserved_hw_block = hw_block_id;
}
- src_pipes_[left_index].reserved = true;
SetDecimationFactor(pipe_info);
pipe_info = &hw_layers->config[i].right_pipe;
if (pipe_info->pipe_id == 0) {
// assign single pipe
- hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
- src_pipes_[left_index].at_right = false;
- hw_layers->config[i].is_right_pipe = false;
- src_pipes_[left_index].at_right = false;
+ if (left_index < num_pipe_) {
+ hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
+ src_pipes_[left_index].at_right = false;
+ }
continue;
}
@@ -248,7 +260,7 @@
uint32_t right_index;
right_index = GetPipe(hw_block_id, is_yuv, need_scale, true, use_non_dma_pipe);
if (right_index >= num_pipe_) {
- goto Acquire_failed;
+ goto CleanupOnError;
}
if (src_pipes_[right_index].priority < src_pipes_[left_index].priority) {
@@ -257,25 +269,31 @@
}
// assign dual pipes
- hw_layers->config[i].right_pipe.pipe_id = src_pipes_[right_index].mdss_pipe_id;
- src_pipes_[right_index].reserved = true;
+ pipe_info->pipe_id = src_pipes_[right_index].mdss_pipe_id;
+ src_pipes_[right_index].reserved_hw_block = hw_block_id;
src_pipes_[right_index].at_right = true;
- src_pipes_[left_index].reserved = true;
+ src_pipes_[left_index].reserved_hw_block = hw_block_id;
src_pipes_[left_index].at_right = false;
hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
SetDecimationFactor(pipe_info);
+
+ DLOGV_IF(kTagResources, "Pipe acquired, layer index = %d, left_pipe = %x, right_pipe = %x",
+ i, hw_layers->config[i].left_pipe.pipe_id, pipe_info->pipe_id);
}
if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
DLOGV_IF(kTagResources, "Bandwidth check failed!");
- goto Acquire_failed;
+ goto CleanupOnError;
}
return kErrorNone;
-Acquire_failed:
- for (uint32_t i = 0; i < num_pipe_; i++)
- src_pipes_[i].reserved = false;
+CleanupOnError:
+ DLOGV_IF(kTagResources, "Resource reserving failed! hw_block = %d", hw_block_id);
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ if (src_pipes_[i].reserved_hw_block == hw_block_id)
+ src_pipes_[i].reserved_hw_block = kHWBlockMax;
+ }
return kErrorResources;
}
@@ -486,6 +504,7 @@
}
void ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
@@ -494,23 +513,23 @@
DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
for (uint32_t i = 0; i < num_pipe_; i++) {
- if (src_pipes_[i].reserved) {
+ if (src_pipes_[i].reserved_hw_block == hw_block_id) {
src_pipes_[i].hw_block_id = hw_block_id;
src_pipes_[i].state = kPipeStateAcquired;
src_pipes_[i].state_frame_count = frame_count;
DLOGV_IF(kTagResources, "Pipe acquired index = %d, type = %d, pipe_id = %x", i,
- src_pipes_[i].type, src_pipes_[i].mdss_pipe_id);
+ src_pipes_[i].type, src_pipes_[i].mdss_pipe_id);
} else if ((src_pipes_[i].hw_block_id == hw_block_id) &&
(src_pipes_[i].state == kPipeStateAcquired)) {
src_pipes_[i].state = kPipeStateToRelease;
src_pipes_[i].state_frame_count = frame_count;
DLOGV_IF(kTagResources, "Pipe to release index = %d, type = %d, pipe_id = %x", i,
- src_pipes_[i].type, src_pipes_[i].mdss_pipe_id);
+ src_pipes_[i].type, src_pipes_[i].mdss_pipe_id);
}
}
// handoff pipes which are used by splash screen
- if (UNLIKELY((frame_count == 1) && (hw_block_id == kHWPrimary))) {
+ if ((frame_count == 1) && (hw_block_id == kHWPrimary)) {
for (uint32_t i = 0; i < num_pipe_; i++) {
if ((src_pipes_[i].state == kPipeStateOwnedByKernel)) {
src_pipes_[i].state = kPipeStateToRelease;
@@ -518,8 +537,7 @@
}
}
}
-
- frame_start_ = false;
+ display_resource_ctx->frame_start = false;
}
void ResManager::Purge(Handle display_ctx) {
@@ -531,11 +549,10 @@
for (uint32_t i = 0; i < num_pipe_; i++) {
if (src_pipes_[i].hw_block_id == hw_block_id)
- src_pipes_[i].state = kPipeStateIdle;
+ src_pipes_[i].ResetState();
}
}
-
uint32_t ResManager::GetMdssPipeId(PipeType type, uint32_t index) {
uint32_t mdss_id = kPipeIdMax;
switch (type) {
@@ -572,34 +589,19 @@
return (1 << mdss_id);
}
-uint32_t ResManager::NextPipe(PipeType type, HWBlockType hw_block_id, bool at_right) {
- uint32_t num_pipe = 0;
+uint32_t ResManager::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
+ uint32_t num_pipe, bool at_right) {
uint32_t index = kPipeIdMax;
- SourcePipe *src_pipe = NULL;
+ SourcePipe *src_pipe;
+ HWBlockType dedicated_block;
- switch (type) {
- case kPipeTypeVIG:
- src_pipe = vig_pipes_;
- num_pipe = hw_res_info_.num_vig_pipe;
- break;
- case kPipeTypeRGB:
- src_pipe = rgb_pipes_;
- num_pipe = hw_res_info_.num_rgb_pipe;
- break;
- case kPipeTypeDMA:
- default:
- src_pipe = dma_pipes_;
- num_pipe = hw_res_info_.num_dma_pipe;
- break;
- }
-
- // search the pipe being used
+ // search dedicated idle pipes
for (uint32_t i = 0; i < num_pipe; i++) {
- if (!src_pipe[i].reserved &&
- (src_pipe[i].state == kPipeStateAcquired) &&
- (src_pipe[i].hw_block_id == hw_block_id) &&
- (src_pipe[i].at_right == at_right)) {
- index = src_pipe[i].index;
+ src_pipe = &src_pipes[i];
+ if (src_pipe->reserved_hw_block == kHWBlockMax &&
+ src_pipe->state == kPipeStateIdle &&
+ src_pipe->dedicated_hw_block == hw_block_id) {
+ index = src_pipe->index;
break;
}
}
@@ -609,19 +611,63 @@
return index;
}
+ // search the pipe being used
for (uint32_t i = 0; i < num_pipe; i++) {
- if (!src_pipe[i].reserved &&
- ((src_pipe[i].state == kPipeStateIdle) ||
- ((src_pipe[i].state == kPipeStateAcquired) &&
- (src_pipe[i].hw_block_id == hw_block_id)))) {
- index = src_pipe[i].index;
+ src_pipe = &src_pipes[i];
+ dedicated_block = src_pipe->dedicated_hw_block;
+ if (src_pipe->reserved_hw_block == kHWBlockMax &&
+ (src_pipe->state == kPipeStateAcquired) &&
+ (src_pipe->hw_block_id == hw_block_id) &&
+ (src_pipe->at_right == at_right) &&
+ (dedicated_block == hw_block_id || dedicated_block == kHWBlockMax)) {
+ index = src_pipe->index;
break;
}
}
+ // found
+ if (index < num_pipe_) {
+ return index;
+ }
+
+ // search the pipes idle or being used but not at the same side
+ for (uint32_t i = 0; i < num_pipe; i++) {
+ src_pipe = &src_pipes[i];
+ dedicated_block = src_pipe->dedicated_hw_block;
+ if (src_pipe->reserved_hw_block == kHWBlockMax &&
+ ((src_pipe->state == kPipeStateIdle) ||
+ (src_pipe->state == kPipeStateAcquired && src_pipe->hw_block_id == hw_block_id)) &&
+ (dedicated_block == hw_block_id || dedicated_block == kHWBlockMax)) {
+ index = src_pipe->index;
+ break;
+ }
+ }
return index;
}
+uint32_t ResManager::NextPipe(PipeType type, HWBlockType hw_block_id, bool at_right) {
+ uint32_t num_pipe = 0;
+ SourcePipe *src_pipes = NULL;
+
+ switch (type) {
+ case kPipeTypeVIG:
+ src_pipes = vig_pipes_;
+ num_pipe = hw_res_info_.num_vig_pipe;
+ break;
+ case kPipeTypeRGB:
+ src_pipes = rgb_pipes_;
+ num_pipe = hw_res_info_.num_rgb_pipe;
+ break;
+ case kPipeTypeDMA:
+ default:
+ src_pipes = dma_pipes_;
+ num_pipe = hw_res_info_.num_dma_pipe;
+ break;
+ }
+
+ return SearchPipe(hw_block_id, src_pipes, num_pipe, at_right);
+}
+
uint32_t ResManager::GetPipe(HWBlockType hw_block_id, bool is_yuv, bool need_scale, bool at_right,
bool use_non_dma_pipe) {
uint32_t index = kPipeIdMax;
@@ -634,7 +680,7 @@
index = NextPipe(kPipeTypeDMA, hw_block_id, at_right);
}
- if ((index >= num_pipe_) && (!need_scale || hw_res_info_.has_non_scalar_rgb)) {
+ if ((index >= num_pipe_) && (!need_scale || !hw_res_info_.has_non_scalar_rgb)) {
index = NextPipe(kPipeTypeRGB, hw_block_id, at_right);
}
@@ -656,6 +702,14 @@
void ResManager::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
+ AppendString(buffer, length, "\nresource manager pipe state");
+ for (uint32_t i = 0; i < num_pipe_; i++) {
+ SourcePipe *src_pipe = &src_pipes_[i];
+ AppendString(buffer, length,
+ "\nindex = %d, id = %x, reserved = %d, state = %d, at_right = %d, dedicated = %d",
+ src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
+ src_pipe->state, src_pipe->at_right, src_pipe->dedicated_hw_block);
+ }
}
} // namespace sde
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index ab1c9c7..88c7fb7 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -39,7 +39,7 @@
DisplayError Init(const HWResourceInfo &hw_res_info);
DisplayError Deinit();
DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
- Handle *display_ctx);
+ Handle *display_ctx);
DisplayError UnregisterDisplay(Handle display_ctx);
DisplayError Start(Handle display_ctx);
DisplayError Stop(Handle display_ctx);
@@ -80,11 +80,12 @@
kPipeStateOwnedByKernel, // Pipe state when pipe is owned by kernel
};
+ // todo: retrieve all these from kernel
enum {
kMaxSourcePipeWidth = 2048,
kMaxInterfaceWidth = 2048,
- kMaxCropWidth = 5,
- kMaxCropHeight = 5,
+ kMaxRotateDownScaleRatio = 8,
+ kMaxNumRotator = 2,
};
struct SourcePipe {
@@ -96,11 +97,17 @@
bool at_right;
uint64_t state_frame_count;
int priority;
- bool reserved;
+ HWBlockType reserved_hw_block;
+ HWBlockType dedicated_hw_block;
- SourcePipe() : type(kPipeTypeUnused), mdss_pipe_id(kPipeIdMax), index(0), state(kPipeStateIdle),
- hw_block_id(kHWBlockMax), at_right(false), state_frame_count(0), priority(0),
- reserved(false) { }
+ SourcePipe() : type(kPipeTypeUnused), mdss_pipe_id(kPipeIdMax), index(0),
+ state(kPipeStateIdle), hw_block_id(kHWBlockMax), at_right(false),
+ state_frame_count(0), priority(0), reserved_hw_block(kHWBlockMax),
+ dedicated_hw_block(kHWBlockMax) { }
+
+ inline void ResetState() { state = kPipeStateIdle; hw_block_id = kHWBlockMax;
+ at_right = false; reserved_hw_block = kHWBlockMax; dedicated_hw_block = kHWBlockMax; }
+
};
struct DisplayResourceContext {
@@ -109,8 +116,10 @@
HWBlockType hw_block_id;
uint64_t frame_count;
int32_t session_id; // applicable for virtual display sessions only
-
- DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1) { }
+ uint32_t rotate_count;
+ bool frame_start;
+ DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
+ rotate_count(0), frame_start(false) { }
};
struct HWBlockContext {
@@ -118,25 +127,46 @@
HWBlockContext() : is_in_use(false) { }
};
+ struct HWRotator {
+ uint32_t pipe_index;
+ HWBlockType writeback_id;
+ uint32_t client_bit_mask;
+ HWRotator() : pipe_index(0), writeback_id(kHWBlockMax), client_bit_mask(0) { }
+ };
+
+ static const int kPipeIdNeedsAssignment = -1;
+
uint32_t GetMdssPipeId(PipeType pipe_type, uint32_t index);
uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id, bool at_right);
+ uint32_t SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe,
+ bool at_right);
uint32_t GetPipe(HWBlockType hw_block_id, bool is_yuv, bool need_scale, bool at_right,
bool use_non_dma_pipe);
bool IsScalingNeeded(const HWPipeInfo *pipe_info);
- DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers);
- bool IsValidDimension(const Layer &layer, float *width_scale, float *height_scale);
- void CalculateCut(float *left_cut_ratio, float *top_cut_ratio, float *right_cut_ratio,
- float *bottom_cut_ratio, const LayerTransform &transform);
- void CalculateCropRects(LayerRect *crop, LayerRect *dst,
- const LayerRect &scissor, const LayerTransform &transform);
- bool IsNonIntegralSrcCrop(const LayerRect &crop);
- void IntegerizeRect(LayerRect *dst_rect, const LayerRect &src_rect);
+ DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers,
+ uint32_t *rotate_count);
+ DisplayError DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+ const Layer &layer, const LayerRect &src_rect,
+ const LayerRect &dst_rect, HWLayerConfig *layer_config);
+ DisplayError ValidateScaling(const Layer &layer, const LayerRect &crop,
+ const LayerRect &dst, float *rot_scale_x, float *rot_scale_y);
+ void CalculateCut(const LayerTransform &transform, float *left_cut_ratio, float *top_cut_ratio,
+ float *right_cut_ratio, float *bottom_cut_ratio);
+ void CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
+ LayerRect *crop, LayerRect *dst);
+ bool IsValidDimension(const LayerRect &src, const LayerRect &dst);
bool CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers);
float GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp);
float GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe);
float GetOverlapBw(HWLayers *hw_layers, float *pipe_bw, bool left_mixer);
void SetDecimationFactor(HWPipeInfo *pipe);
float GetBpp(LayerBufferFormat format);
+ void SplitRect(bool flip_horizontal, const LayerRect &src_rect, const LayerRect &dst_rect,
+ LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
+ LayerRect *dst_right);
+ bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
+ bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
+ void LogRectVerbose(const char *prefix, const LayerRect &roi);
template <class T>
inline void Swap(T &a, T &b) {
@@ -157,6 +187,7 @@
float bw_claimed_; // Bandwidth claimed by other display
float clk_claimed_; // Clock claimed by other display
float last_primary_bw_;
+ uint32_t virtual_count_;
};
} // namespace sde