sdm: Add support for draw cycles without GPUTarget layer.
- Make GPUTarget layer optional. Return error upon Prepare() call if
draw cycle is not feasible without GPU support.
- Fix interface documentation.
CRs-Fixed: 1054762
Change-Id: I107a3bfbd1849804467a8f09c5d8702cb31dd5ea
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 39b54c7..0fcab25 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -64,39 +64,65 @@
@sa Layer
*/
enum LayerComposition {
+ /* ==== List of composition types set by SDM === */
+ /* These composition types represent SDM composition decision for the layers which need to
+ be blended. Composition types are set during Prepare() by SDM.
+ Client can set default composition type to any of the below before calling into Prepare(),
+ however client's input value is ignored and does not play any role in composition decision.
+ */
kCompositionGPU, //!< This layer will be drawn onto the target buffer by GPU. Display
- //!< device will mark the layer for GPU composition if it can not handle
- //!< it completely.
+ //!< device will mark the layer for GPU composition if it can not
+ //!< handle composition for it.
+ //!< This composition type is used only if GPUTarget layer is provided
+ //!< in a composition cycle.
kCompositionGPUS3D, //!< This layer will be drawn onto the target buffer in s3d mode by GPU.
- //!< Display device should mark the layer for GPU composition if it can
- //!< not handle it completely.
+ //!< Display device will mark the layer for GPU composition if it can
+ //!< not handle composition for it.
+ //!< This composition type is used only if GPUTarget layer is provided
+ //!< in a composition cycle.
- kCompositionSDE, //!< This layer will be handled by SDE. It must not be composed by GPU.
+ kCompositionSDE, //!< This layer will be composed by SDE. It must not be composed by
+ //!< GPU or Blit.
- kCompositionHWCursor, //!< This layer will be handled by SDE using HWCursor. It must not be
- //!< composed by GPU
+ kCompositionHWCursor, //!< This layer will be composed by SDE using HW Cursor. It must not be
+ //!< composed by GPU or Blit.
- kCompositionHybrid, //!< This layer will be drawn by a blit engine and SDE together. Display
- //!< device will split the layer, update the blit rectangle that
- //!< need to be composed by a blit engine and update original source
- //!< rectangle that will be composed by SDE.
+ kCompositionHybrid, //!< This layer will be drawn by a blit engine and SDE together.
+ //!< Display device will split the layer, update the blit rectangle
+ //!< that need to be composed by a blit engine and update original
+ //!< source rectangle that will be composed by SDE.
+ //!< This composition type is used only if GPUTarget and BlitTarget
+ //!< layers are provided in a composition cycle.
- kCompositionBlit, //!< This layer will be composed using Blit Engine
+ kCompositionBlit, //!< This layer will be composed using Blit Engine.
+ //!< This composition type is used only if BlitTarget layer is provided
+ //!< in a composition cycle.
+ /* === List of composition types set by Client === */
+ /* These composition types represent target buffer layers onto which GPU or Blit will draw if SDM
+ decide to have some or all layers drawn by respective composition engine.
+ If client does not provide a target buffer layer, SDM will assume that respective composition
+ engine is not available and will not mark any layer for such a composition. If SDM is unable
+ to handle layers without support of such a composition engine, Prepare() call will return
+ failure.
+ */
kCompositionGPUTarget, //!< This layer will hold result of composition for layers marked for
//!< GPU composition.
- //!< If display device does not set any layer for SDE composition then
- //!< this would be ignored during Commit().
+ //!< If display device does not set any layer for GPU composition then
+ //!< this layer would be ignored. Else, this layer will be composed
+ //!< with other layers marked for SDE composition by SDE.
//!< Only one layer shall be marked as target buffer by the caller.
- //!< GPU target layer shall be after application layers in layer stack.
+ //!< GPU target layer shall be placed after all application layers
+ //!< in the layer stack.
kCompositionBlitTarget, //!< This layer will hold result of composition for blit rectangles
//!< from the layers marked for hybrid composition. Nth blit rectangle
//!< in a layer shall be composed onto Nth blit target.
//!< If display device does not set any layer for hybrid composition
- //!< then this would be ignored during Commit().
- //!< Blit target layers shall be after GPU target layer in layer stack.
+ //!< then this would be ignored.
+ //!< Blit target layers shall be placed after GPUTarget in the layer
+ //!< stack.
};
/*! @brief This structure defines rotation and flip values for a display layer.
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index fd84fc1..4ae696d 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -418,6 +418,8 @@
struct HWLayersInfo {
LayerStack *stack = NULL; // Input layer stack. Set by the caller.
+ uint32_t app_layer_count = 0; // Total number of app layers. Must not be 0.
+ uint32_t gpu_target_index = 0; // GPU target layer index. 0 if not present.
uint32_t index[kMaxSDELayers]; // Indexes of the layers from the layer stack which need to be
// programmed on hardware.
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 0e48f2c..b1a34d1 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -136,28 +136,39 @@
return kErrorNone;
}
-DisplayError DisplayBase::ValidateGPUTarget(LayerStack *layer_stack) {
- uint32_t i = 0;
- std::vector<Layer *>layers = layer_stack->layers;
+DisplayError DisplayBase::BuildLayerStackStats(LayerStack *layer_stack) {
+ std::vector<Layer *> &layers = layer_stack->layers;
+ HWLayersInfo &hw_layers_info = hw_layers_.info;
- // TODO(user): Remove this check once we have query display attributes on virtual display
- if (display_type_ == kVirtual) {
- return kErrorNone;
- }
- uint32_t layer_count = UINT32(layers.size());
- while ((i < layer_count) && (layers.at(i)->composition != kCompositionGPUTarget)) {
- i++;
+ hw_layers_info.stack = layer_stack;
+
+ for (auto &layer : layers) {
+ if (layer->composition == kCompositionGPUTarget) {
+ hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+ break;
+ }
+ hw_layers_info.app_layer_count++;
}
- if (i >= layer_count) {
- DLOGE("Either layer count is zero or GPU target layer is not present");
+ DLOGV_IF(kTagNone, "LayerStack layer_count: %d, app_layer_count: %d, gpu_target_index: %d, "
+ "display type: %d", layers.size(), hw_layers_info.app_layer_count,
+ hw_layers_info.gpu_target_index, display_type_);
+
+ if (!hw_layers_info.app_layer_count) {
+ DLOGE("Layer count is zero");
return kErrorParameters;
}
- uint32_t gpu_target_index = i;
+ if (hw_layers_info.gpu_target_index) {
+ return ValidateGPUTargetParams();
+ }
- // Check GPU target layer
- Layer *gpu_target_layer = layers.at(gpu_target_index);
+ return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateGPUTargetParams() {
+ HWLayersInfo &hw_layers_info = hw_layers_.info;
+ Layer *gpu_target_layer = hw_layers_info.stack->layers.at(hw_layers_info.gpu_target_index);
if (!IsValid(gpu_target_layer->src_rect)) {
DLOGE("Invalid src rect for GPU target layer");
@@ -184,9 +195,9 @@
if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
- DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f mixer wxh %dx%d",
- gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels, mixer_attributes_.width,
- mixer_attributes_.height);
+ DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f, mixer wxh %dx%d",
+ gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels,
+ mixer_attributes_.width, mixer_attributes_.height);
return kErrorParameters;
}
@@ -205,7 +216,7 @@
return kErrorParameters;
}
- error = ValidateGPUTarget(layer_stack);
+ error = BuildLayerStackStats(layer_stack);
if (error != kErrorNone) {
return error;
}
@@ -219,9 +230,6 @@
disable_pu_one_frame_ = false;
}
- hw_layers_.info.stack = layer_stack;
- hw_layers_.output_compression = 1.0f;
-
comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
while (true) {
error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 91bbc37..2bc94b7 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -113,12 +113,14 @@
virtual bool IsPrimaryDisplay();
protected:
+ DisplayError BuildLayerStackStats(LayerStack *layer_stack);
+ virtual DisplayError ValidateGPUTargetParams();
+
// DumpImpl method
void AppendDump(char *buffer, uint32_t length);
bool IsRotationRequired(HWLayers *hw_layers);
const char *GetName(const LayerComposition &composition);
- DisplayError ValidateGPUTarget(LayerStack *layer_stack);
DisplayError ReconfigureDisplay();
bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
uint32_t *new_mixer_height);
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index 3207ec1..d6ce915 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -62,6 +62,11 @@
virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
return kErrorNotSupported;
}
+ virtual DisplayError ValidateGPUTargetParams() {
+ // TODO(user): Validate GPU target for virtual display when query display attributes
+ // on virtual display is functional.
+ return kErrorNone;
+ }
};
} // namespace sdm
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 8519f7e..7a983e5 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -80,19 +80,6 @@
hw_layers_info_ = hw_layers_info;
extn_start_success_ = false;
tried_default_ = false;
- uint32_t i = 0;
- LayerStack *layer_stack = hw_layers_info_->stack;
- uint32_t layer_count = UINT32(layer_stack->layers.size());
- for (; i < layer_count; i++) {
- if (layer_stack->layers.at(i)->composition == kCompositionGPUTarget) {
- fb_layer_index_ = i;
- break;
- }
- }
-
- if (i == layer_count) {
- return kErrorUndefined;
- }
if (partial_update_intf_) {
partial_update_intf_->ControlPartialUpdate(partial_update_enable);
@@ -130,6 +117,11 @@
}
}
+ // Default composition is not possible if GPU composition is not supported.
+ if (!hw_layers_info_->gpu_target_index) {
+ return kErrorNotSupported;
+ }
+
// Default composition is already tried.
if (tried_default_) {
return kErrorUndefined;
@@ -141,25 +133,17 @@
uint32_t &hw_layer_count = hw_layers_info_->count;
hw_layer_count = 0;
- for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
- Layer *layer = layer_stack->layers.at(i);
- LayerComposition &composition = layer->composition;
- if (composition == kCompositionGPUTarget) {
- hw_layers_info_->updated_src_rect[hw_layer_count] = layer->src_rect;
- hw_layers_info_->updated_dst_rect[hw_layer_count] = layer->dst_rect;
- hw_layers_info_->index[hw_layer_count++] = i;
- } else if (composition != kCompositionBlitTarget) {
- composition = kCompositionGPU;
- }
+ for (uint32_t i = 0; i < hw_layers_info_->app_layer_count; i++) {
+ layer_stack->layers.at(i)->composition = kCompositionGPU;
}
+ Layer *gpu_target_layer = layer_stack->layers.at(hw_layers_info_->gpu_target_index);
+ hw_layers_info_->updated_src_rect[hw_layer_count] = gpu_target_layer->src_rect;
+ hw_layers_info_->updated_dst_rect[hw_layer_count] = gpu_target_layer->dst_rect;
+ hw_layers_info_->index[hw_layer_count++] = hw_layers_info_->gpu_target_index;
+
tried_default_ = true;
- // There can be one and only one GPU target buffer.
- if (hw_layer_count != 1) {
- return kErrorParameters;
- }
-
return kErrorNone;
}
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index b284d61..8b4b6f4 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -62,7 +62,6 @@
HWMixerAttributes mixer_attributes_ = {};
HWDisplayAttributes display_attributes_ = {};
DisplayConfigVariableInfo fb_config_ = {};
- uint32_t fb_layer_index_ = 0;
bool extn_start_success_ = false;
bool tried_default_ = false;
};