Skip to content

Commit

Permalink
sdm: Add support for draw cycles without GPUTarget layer.
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
Dileep Marchya authored and Gerrit - the friendly Code Review server committed Aug 25, 2016
1 parent f2ecade commit da3f632
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 74 deletions.
70 changes: 48 additions & 22 deletions sdm/include/core/layer_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,39 +64,65 @@ enum LayerBlending {
@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.

kCompositionSDE, //!< This layer will be handled by SDE. It must not be composed by GPU.

kCompositionHWCursor, //!< This layer will be handled by SDE using HWCursor. It must not be
//!< composed by GPU

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.

kCompositionBlit, //!< This layer will be composed using Blit Engine

//!< 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 composed by SDE. It must not be composed by
//!< GPU or Blit.

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.
//!< 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.
//!< 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.
Expand Down
2 changes: 2 additions & 0 deletions sdm/include/private/hw_info_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ struct HWLayerConfig {

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.
Expand Down
52 changes: 30 additions & 22 deletions sdm/libs/core/display_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,28 +136,39 @@ DisplayError DisplayBase::Deinit() {
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");
Expand All @@ -184,9 +195,9 @@ DisplayError DisplayBase::ValidateGPUTarget(LayerStack *layer_stack) {

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;
}

Expand All @@ -205,7 +216,7 @@ DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
return kErrorParameters;
}

error = ValidateGPUTarget(layer_stack);
error = BuildLayerStackStats(layer_stack);
if (error != kErrorNone) {
return error;
}
Expand All @@ -219,9 +230,6 @@ DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
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_);
Expand Down
4 changes: 3 additions & 1 deletion sdm/libs/core/display_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,14 @@ class DisplayBase : public DisplayInterface, DumpImpl {
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);
Expand Down
5 changes: 5 additions & 0 deletions sdm/libs/core/display_virtual.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class DisplayVirtual : public DisplayBase {
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
Expand Down
40 changes: 12 additions & 28 deletions sdm/libs/core/strategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,6 @@ DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempt
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);
Expand Down Expand Up @@ -130,6 +117,11 @@ DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
}
}

// 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;
Expand All @@ -141,24 +133,16 @@ DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
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;
}

tried_default_ = true;
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;

// There can be one and only one GPU target buffer.
if (hw_layer_count != 1) {
return kErrorParameters;
}
tried_default_ = true;

return kErrorNone;
}
Expand Down
1 change: 0 additions & 1 deletion sdm/libs/core/strategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ class Strategy {
HWMixerAttributes mixer_attributes_ = {};
HWDisplayAttributes display_attributes_ = {};
DisplayConfigVariableInfo fb_config_ = {};
uint32_t fb_layer_index_ = 0;
bool extn_start_success_ = false;
bool tried_default_ = false;
};
Expand Down

0 comments on commit da3f632

Please sign in to comment.