state.surface_ = surface;
size_t num_regions = comp_regions.size();
state.states_.reserve(num_regions);
+ bool use_plane_transform = false;
+ if (plane.GetRotationType() ==
+ DisplayPlaneState::RotationType::kGPURotation) {
+ use_plane_transform = true;
+ }
+
if (!CalculateRenderState(layers, comp_regions, state,
- plane.IsUsingPlaneScalar())) {
+ plane.IsUsingPlaneScalar(),
+ use_plane_transform)) {
ETRACE("Failed to calculate Render state.");
return false;
}
bool Compositor::CalculateRenderState(
std::vector<OverlayLayer> &layers,
const std::vector<CompositionRegion> &comp_regions, DrawState &draw_state,
- bool uses_display_up_scaling) {
+ bool uses_display_up_scaling, bool use_plane_transform) {
CTRACE();
size_t num_regions = comp_regions.size();
for (size_t region_index = 0; region_index < num_regions; region_index++) {
const CompositionRegion ®ion = comp_regions.at(region_index);
RenderState state;
- state.ConstructState(layers, region, uses_display_up_scaling);
+ state.ConstructState(layers, region, uses_display_up_scaling,
+ use_plane_transform);
if (state.layer_state_.empty()) {
continue;
}
private:
bool CalculateRenderState(std::vector<OverlayLayer> &layers,
const std::vector<CompositionRegion> &comp_regions,
- DrawState &state, bool uses_display_up_scaling);
+ DrawState &state, bool uses_display_up_scaling,
+ bool use_plane_transform = false);
void SeparateLayers(const std::vector<size_t> &dedicated_layers,
const std::vector<size_t> &source_layers,
const std::vector<HwcRect<int>> &display_frame,
clear_surface_ = clear_surface;
}
-void NativeSurface::SetDisplayRotation(HWCRotation rotation) {
- layer_.SetDisplayRotation(rotation);
+void NativeSurface::SetTransform(uint32_t transform) {
+ layer_.SetTransform(transform);
}
void NativeSurface::SetSurfaceAge(uint32_t value) {
return surface_damage_;
}
- // Rotates this surface to rotation.
- void SetDisplayRotation(HWCRotation rotation);
+ // Applies rotation transform to this surface.
+ void SetTransform(uint32_t transform);
protected:
OverlayLayer layer_;
bool in_use_;
ClearType clear_surface_;
uint32_t surface_age_;
- HWCRotation rotation_ = kRotateNone;
HwcRect<int> surface_damage_;
HwcRect<int> last_surface_damage_;
};
void RenderState::ConstructState(std::vector<OverlayLayer> &layers,
const CompositionRegion ®ion,
- bool uses_display_up_scaling) {
+ bool uses_display_up_scaling,
+ bool use_plane_transform) {
float bounds[4];
std::copy_n(region.frame.bounds, 4, bounds);
x_ = bounds[0];
src.layer_index_ = texture_index;
bool swap_xy = false;
bool flip_xy[2] = {false, false};
- switch (layer.GetTransform()) {
+ uint32_t transform = layer.GetTransform();
+ if (use_plane_transform) {
+ transform = layer.GetPlaneTransform();
+ }
+
+ switch (transform) {
case HWCTransform::kTransform180: {
swap_xy = false;
flip_xy[0] = true;
}
case HWCTransform::kTransform90: {
swap_xy = true;
- if (layer.GetTransform() & HWCTransform::kReflectX) {
+ if (transform & HWCTransform::kReflectX) {
flip_xy[0] = true;
flip_xy[1] = true;
- } else if (layer.GetTransform() & HWCTransform::kReflectY) {
+ } else if (transform & HWCTransform::kReflectY) {
flip_xy[0] = false;
flip_xy[1] = false;
} else {
void ConstructState(std::vector<OverlayLayer> &layers,
const CompositionRegion ®ion,
- bool uses_display_up_scaling);
+ bool uses_display_up_scaling, bool use_plane_transform);
uint32_t x_;
uint32_t y_;
surface_damage_ = display_frame;
}
-void OverlayLayer::SetDisplayRotation(HWCRotation rotation) {
- ValidateTransform(transform_, rotation);
+void OverlayLayer::SetTransform(uint32_t transform) {
+ plane_transform_ = transform;
+ transform_ = transform;
}
void OverlayLayer::ValidateTransform(uint32_t transform,
uint32_t display_transform) {
if (transform & kTransform90) {
switch (display_transform) {
- case kRotate90:
+ case HWCTransform::kTransform90:
plane_transform_ |= kTransform180;
break;
- case kRotate180:
+ case HWCTransform::kTransform180:
plane_transform_ |= kTransform270;
break;
- case kRotateNone:
+ case HWCTransform::kIdentity:
plane_transform_ |= kTransform90;
if (transform & kReflectX) {
plane_transform_ |= kReflectX;
}
} else if (transform & kTransform180) {
switch (display_transform) {
- case kRotate90:
+ case HWCTransform::kTransform90:
plane_transform_ |= kTransform270;
break;
- case kRotate270:
+ case HWCTransform::kTransform270:
plane_transform_ |= kTransform90;
break;
- case kRotateNone:
+ case HWCTransform::kIdentity:
plane_transform_ |= kTransform180;
break;
default:
}
} else if (transform & kTransform270) {
switch (display_transform) {
- case kRotate270:
+ case HWCTransform::kTransform270:
plane_transform_ |= kTransform180;
break;
- case kRotate180:
+ case HWCTransform::kTransform180:
plane_transform_ |= kTransform90;
break;
- case kRotateNone:
+ case HWCTransform::kIdentity:
plane_transform_ |= kTransform270;
break;
default:
break;
}
} else {
- if (display_transform == kRotate90) {
+ if (display_transform & HWCTransform::kTransform90) {
if (transform & kReflectX) {
plane_transform_ |= kReflectX;
}
plane_transform_ |= kTransform90;
} else {
switch (display_transform) {
- case kRotate270:
+ case HWCTransform::kTransform270:
plane_transform_ |= kTransform270;
break;
- case kRotate180:
+ case HWCTransform::kTransform180:
plane_transform_ |= kTransform180;
break;
default:
ResourceManager* resource_manager,
OverlayLayer* previous_layer,
uint32_t z_order, uint32_t layer_index,
- uint32_t max_height, HWCRotation rotation,
+ uint32_t max_height, uint32_t rotation,
bool handle_constraints) {
transform_ = layer->GetTransform();
if (rotation != kRotateNone) {
ValidateTransform(layer->GetTransform(), rotation);
- transform_ = plane_transform_;
} else {
plane_transform_ = transform_;
}
void OverlayLayer::InitializeFromHwcLayer(
HwcLayer* layer, ResourceManager* resource_manager,
OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
- uint32_t max_height, HWCRotation rotation, bool handle_constraints) {
+ uint32_t max_height, uint32_t rotation, bool handle_constraints) {
display_frame_width_ = layer->GetDisplayFrameWidth();
display_frame_height_ = layer->GetDisplayFrameHeight();
display_frame_ = layer->GetDisplayFrame();
void OverlayLayer::InitializeFromScaledHwcLayer(
HwcLayer* layer, ResourceManager* resource_manager,
OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
- const HwcRect<int>& display_frame, uint32_t max_height,
- HWCRotation rotation, bool handle_constraints) {
+ const HwcRect<int>& display_frame, uint32_t max_height, uint32_t rotation,
+ bool handle_constraints) {
SetDisplayFrame(display_frame);
InitializeState(layer, resource_manager, previous_layer, z_order, layer_index,
max_height, rotation, handle_constraints);
void InitializeFromHwcLayer(HwcLayer* layer, ResourceManager* buffer_manager,
OverlayLayer* previous_layer, uint32_t z_order,
uint32_t layer_index, uint32_t max_height,
- HWCRotation rotation, bool handle_constraints);
+ uint32_t rotation, bool handle_constraints);
void InitializeFromScaledHwcLayer(HwcLayer* layer,
ResourceManager* buffer_manager,
OverlayLayer* previous_layer,
uint32_t z_order, uint32_t layer_index,
const HwcRect<int>& display_frame,
- uint32_t max_height, HWCRotation rotation,
+ uint32_t max_height, uint32_t rotation,
bool handle_constraints);
// Get z order of this layer.
uint32_t GetZorder() const {
return blending_;
}
+ // This represents the transform to
+ // be applied to this layer without taking
+ // into account any Display transform i.e.
+ // GetPlaneTransform()
uint32_t GetTransform() const {
return transform_;
}
return plane_transform_;
}
- // Rotates this layer to rotation.
- void SetDisplayRotation(HWCRotation rotation);
+ // Applies transform to this layer before scanout.
+ void SetTransform(uint32_t transform);
OverlayBuffer* GetBuffer() const;
void InitializeState(HwcLayer* layer, ResourceManager* buffer_manager,
OverlayLayer* previous_layer, uint32_t z_order,
uint32_t layer_index, uint32_t max_height,
- HWCRotation rotation, bool handle_constraints);
+ uint32_t rotation, bool handle_constraints);
uint32_t transform_ = 0;
uint32_t plane_transform_ = 0;
validate_final_layers = false;
test_commit_done = true;
if (!fall_back || prefer_seperate_plane) {
- composition.emplace_back(plane, layer, layer->GetZorder());
+ composition.emplace_back(plane, layer, layer->GetZorder(),
+ display_transform_);
#ifdef SURFACE_TRACING
ISURFACETRACE("Added Layer for direct Scanout: %d \n",
layer->GetZorder());
break;
} else {
if (composition.empty()) {
- // If we are here, it means the layer failed with
- // Primary. Let's force GPU for all layers.
- // FIXME: We should try to use overlay for
- // other layers in this case.
- ForceGpuForAllLayers(commit_planes, composition, layers, mark_later,
- false);
- return true;
+ bool force_all_layers = true;
+ if (display_transform_ != kIdentity) {
+ composition.emplace_back(plane, layer, layer->GetZorder(),
+ display_transform_);
+ DisplayPlaneState &last_plane = composition.back();
+ ResetPlaneTarget(last_plane, commit_planes.back());
+ // If DisplayTransform is not supported, let's check if
+ // we can fallback to GPU rotation for this plane.
+ if (last_plane.GetRotationType() ==
+ DisplayPlaneState::RotationType::kDisplayRotation) {
+ last_plane.SetRotationType(
+ DisplayPlaneState::RotationType::kGPURotation, false);
+
+ // Check if we can rotate using Display plane.
+ if (!FallbacktoGPU(last_plane.GetDisplayPlane(),
+ last_plane.GetOffScreenTarget()->GetLayer(),
+ commit_planes)) {
+ force_all_layers = false;
+ validate_final_layers = true;
+ }
+ }
+ }
+
+ if (force_all_layers) {
+ // If we are here, it means the layer failed with
+ // Primary. Let's force GPU for all layers.
+ // FIXME: We should try to use overlay for
+ // other layers in this case.
+ ForceGpuForAllLayers(commit_planes, composition, layers,
+ mark_later, false);
+ return true;
+ }
} else {
commit_planes.pop_back();
DisplayPlaneState &last_plane = composition.back();
} else if (add_index > 0) {
SwapSurfaceIfNeeded(&last_plane);
}
+
+ ValidateForDisplayTransform(last_plane, commit_planes);
}
}
}
}
commit_planes.back().layer = last_plane.GetOverlayLayer();
+ ValidateForDisplayTransform(last_plane, commit_planes);
}
}
}
for (DisplayPlaneState &plane : composition) {
if (plane.NeedsOffScreenComposition()) {
plane.RefreshSurfacesIfNeeded();
+ plane.ValidateReValidation();
if (!render_layers) {
render_layers = !plane.SurfaceRecycled();
}
- render_layers = true;
- if (plane.IsRevalidationNeeded() !=
+ if (plane.RevalidationType() !=
DisplayPlaneState::ReValidationType::kNone) {
re_validation = true;
}
}
last_plane->UsePlaneScalar(false);
+ ValidateForDisplayTransform(*last_plane, commit_planes);
} else {
- composition.emplace_back(plane, cursor_layer, cursor_layer->GetZorder());
+ composition.emplace_back(plane, cursor_layer, cursor_layer->GetZorder(),
+ display_transform_);
#ifdef SURFACE_TRACING
ISURFACETRACE("Added CursorLayer for direct scanout: %d \n",
cursor_layer->GetZorder());
PreparePlaneForCursor(last_plane, mark_later, validate_final_layers,
is_video, recycle_resources);
last_plane->UsePlaneScalar(false);
+ ValidateForDisplayTransform(*last_plane, commit_planes);
+ }
+}
+
+void DisplayPlaneManager::ValidateForDisplayTransform(
+ DisplayPlaneState &last_plane,
+ const std::vector<OverlayPlane> &commit_planes) const {
+ if (display_transform_ != kIdentity) {
+ // No need for any check if we are relying on rotation during
+ // 3D Composition pass.
+ if (last_plane.GetRotationType() ==
+ DisplayPlaneState::RotationType::kGPURotation) {
+ return;
+ }
+
+ last_plane.ValidateReValidation();
+ if (last_plane.RevalidationType() &
+ DisplayPlaneState::ReValidationType::kRotation) {
+ uint32_t validation_done = DisplayPlaneState::ReValidationType::kRotation;
+ // Ensure Rotation doesn't impact the results.
+ if (FallbacktoGPU(last_plane.GetDisplayPlane(),
+ last_plane.GetOffScreenTarget()->GetLayer(),
+ commit_planes)) {
+ last_plane.SetRotationType(
+ DisplayPlaneState::RotationType::kGPURotation, false);
+ }
+
+ last_plane.RevalidationDone(validation_done);
+ }
}
}
// If we are here this means the layer cannot be scaled using display, just
// return.
if (!ignore_format &&
- (current_layer->GetPlaneTransform() == HWCTransform::kIdentity) &&
+ (current_layer->GetTransform() == HWCTransform::kIdentity) &&
last_plane.GetDisplayPlane()->IsSupportedFormat(
current_layer->GetBuffer()->GetFormat())) {
return;
surfaces.swap(surfaces_);
}
-void DisplayPlaneManager::SetDisplayRotation(HWCRotation rotation) {
- rotation_ = rotation;
+void DisplayPlaneManager::SetDisplayTransform(uint32_t transform) {
+ display_transform_ = transform;
}
void DisplayPlaneManager::EnsureOffScreenTarget(DisplayPlaneState &plane) {
}
surface->SetPlaneTarget(plane, gpu_fd_);
- if (rotation_ != kRotateNone)
- surface->SetDisplayRotation(rotation_);
-
plane.SetOffScreenTarget(surface);
}
DisplayPlane *current_plane = overlay_planes_.at(0).get();
composition.emplace_back(current_plane, primary_layer,
- primary_layer->GetZorder());
+ primary_layer->GetZorder(), display_transform_);
DisplayPlaneState &last_plane = composition.back();
last_plane.ForceGPURendering();
layer_begin++;
continue;
}
- if (last_plane.IsRevalidationNeeded() ==
- DisplayPlaneState::ReValidationType::kScanout) {
+ uint32_t revalidation_type = last_plane.RevalidationType();
+
+ if (!revalidation_type) {
+ render = true;
+ index++;
+ continue;
+ }
+
+ uint32_t validation_done = DisplayPlaneState::ReValidationType::kScanout;
+ if (revalidation_type & DisplayPlaneState::ReValidationType::kScanout) {
const std::vector<size_t> &source_layers = last_plane.GetSourceLayers();
bool uses_scalar = last_plane.IsUsingPlaneScalar();
// Store current layer to re-set in case commit fails.
#endif
MarkSurfacesForRecycling(&last_plane, mark_later, false);
}
- } else if (last_plane.IsRevalidationNeeded() ==
- DisplayPlaneState::ReValidationType::kScalar) {
+ }
+
+ render = true;
+ index++;
+ if (revalidation_type & DisplayPlaneState::ReValidationType::kScalar) {
ValidateForDisplayScaling(last_plane, commit_planes,
last_plane.GetOffScreenTarget()->GetLayer(),
true);
+ validation_done |= DisplayPlaneState::ReValidationType::kScalar;
}
- render = true;
- last_plane.RevalidationDone();
- index++;
+ if (revalidation_type & DisplayPlaneState::ReValidationType::kRotation) {
+ validation_done |= DisplayPlaneState::ReValidationType::kRotation;
+ // Save old rotation type.
+ DisplayPlaneState::RotationType old_type = last_plane.GetRotationType();
+ DisplayPlaneState::RotationType new_type = old_type;
+ if (old_type == DisplayPlaneState::RotationType::kGPURotation) {
+ last_plane.SetRotationType(
+ DisplayPlaneState::RotationType::kDisplayRotation, false);
+ } else if (re_validate_commit) {
+ // We should have already done a full commit check above.
+ // As their is no state change we can avoid another test
+ // commit here.
+ last_plane.RevalidationDone(validation_done);
+ continue;
+ }
+
+ // Check if we can rotate using Display plane.
+ if (FallbacktoGPU(last_plane.GetDisplayPlane(),
+ last_plane.GetOffScreenTarget()->GetLayer(),
+ commit_planes)) {
+ new_type = DisplayPlaneState::RotationType::kGPURotation;
+ }
+
+ // Set new rotation type. Clear surfaces in case type has changed.
+ last_plane.SetRotationType(new_type, new_type != old_type);
+ }
+
+ last_plane.RevalidationDone(validation_done);
}
return render;
return height_;
}
- // This is the rotation to which physical pipe
- // associated with this plane manager is rotated.
- void SetDisplayRotation(HWCRotation rotation);
+ // Transform to be applied to all planes associated
+ // with pipe of this displayplanemanager.
+ void SetDisplayTransform(uint32_t transform);
private:
struct LayerResultCache {
OverlayLayer *current_layer,
bool ignore_format = false);
+ void ValidateForDisplayTransform(
+ DisplayPlaneState &last_plane,
+ const std::vector<OverlayPlane> &commit_planes) const;
+
void ForceGpuForAllLayers(std::vector<OverlayPlane> &commit_planes,
DisplayPlaneStateList &composition,
std::vector<OverlayLayer> &layers,
uint32_t width_;
uint32_t height_;
uint32_t gpu_fd_;
- HWCRotation rotation_ = kRotateNone;
+ uint32_t display_transform_ = kIdentity;
};
} // namespace hwcomposer
namespace hwcomposer {
DisplayPlaneState::DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer,
- uint32_t index) {
+ uint32_t index, uint32_t plane_transform) {
private_data_ = std::make_shared<DisplayPlanePrivateState>();
private_data_->source_layers_.emplace_back(index);
private_data_->display_frame_ = layer->GetDisplayFrame();
- private_data_->check_display_scalar_ = true;
+ private_data_->rect_updated_ = true;
private_data_->source_crop_ = layer->GetSourceCrop();
if (layer->IsCursorLayer()) {
private_data_->type_ = DisplayPlanePrivateState::PlaneType::kCursor;
plane->SetInUse(true);
private_data_->plane_ = plane;
private_data_->layer_ = layer;
+ private_data_->plane_transform_ = plane_transform;
+ if (!private_data_->plane_->IsSupportedTransform(plane_transform)) {
+ private_data_->rotation_type_ =
+ DisplayPlaneState::RotationType::kGPURotation;
+ private_data_->unsupported_siplay_rotation_ = true;
+ } else {
+ private_data_->rotation_type_ = RotationType::kDisplayRotation;
+ }
}
void DisplayPlaneState::CopyState(DisplayPlaneState &state) {
void DisplayPlaneState::AddLayer(const OverlayLayer *layer) {
const HwcRect<int> &display_frame = layer->GetDisplayFrame();
- HwcRect<int> &target_display_frame = private_data_->display_frame_;
+ HwcRect<int> target_display_frame = private_data_->display_frame_;
target_display_frame.left =
std::min(target_display_frame.left, display_frame.left);
target_display_frame.top =
target_display_frame.bottom =
std::max(target_display_frame.bottom, display_frame.bottom);
- HwcRect<float> &target_source_crop = private_data_->source_crop_;
+ HwcRect<float> target_source_crop = private_data_->source_crop_;
const HwcRect<float> &source_crop = layer->GetSourceCrop();
target_source_crop.left = std::min(target_source_crop.left, source_crop.left);
target_source_crop.top = std::min(target_source_crop.top, source_crop.top);
private_data_->state_ = DisplayPlanePrivateState::State::kRender;
+ // If layers are less than 2, we need to enforce rect checks as
+ // we shouldn't have done them yet (i.e. Previous state could have
+ // been direct scanout.)
+ bool rect_updated = true;
+ if (private_data_->source_layers_.size() > 2 &&
+ (private_data_->display_frame_ == target_display_frame) &&
+ ((private_data_->source_crop_ == target_source_crop))) {
+ rect_updated = false;
+ } else {
+ private_data_->display_frame_ = target_display_frame;
+ private_data_->source_crop_ = target_source_crop;
+ }
+
+ if (!private_data_->rect_updated_)
+ private_data_->rect_updated_ = rect_updated;
+
if (!private_data_->has_cursor_layer_)
private_data_->has_cursor_layer_ = layer->IsCursorLayer();
}
// Reset Validation state.
- if (re_validate_layer_ == ReValidationType::kScanout)
- re_validate_layer_ = ReValidationType::kNone;
+ if (re_validate_layer_ & ReValidationType::kScanout)
+ re_validate_layer_ &= ~ReValidationType::kScanout;
refresh_needed_ = true;
}
#endif
private_data_->source_layers_.swap(source_layers);
- private_data_->display_frame_ = target_display_frame;
- private_data_->source_crop_ = target_source_crop;
- private_data_->check_display_scalar_ = true;
+ bool rect_updated = true;
+ if ((private_data_->display_frame_ == target_display_frame) &&
+ ((private_data_->source_crop_ == target_source_crop))) {
+ rect_updated = false;
+ } else {
+ private_data_->display_frame_ = target_display_frame;
+ private_data_->source_crop_ = target_source_crop;
+ }
+
+ if (!private_data_->rect_updated_)
+ private_data_->rect_updated_ = rect_updated;
if (private_data_->source_layers_.size() == 1) {
if (private_data_->has_cursor_layer_) {
} else {
private_data_->type_ = DisplayPlanePrivateState::PlaneType::kNormal;
}
+
+ if (!has_video)
+ re_validate_layer_ |= ReValidationType::kScanout;
} else {
private_data_->type_ = DisplayPlanePrivateState::PlaneType::kNormal;
}
std::max(target_display_frame.right, display_frame.right);
target_display_frame.bottom =
std::max(target_display_frame.bottom, display_frame.bottom);
- private_data_->check_display_scalar_ = true;
refresh_needed_ = true;
}
std::max(target_source_crop.right, source_crop.right);
target_source_crop.bottom =
std::max(target_source_crop.bottom, source_crop.bottom);
- private_data_->check_display_scalar_ = true;
refresh_needed_ = true;
}
void DisplayPlaneState::SetOffScreenTarget(NativeSurface *target) {
private_data_->layer_ = target->GetLayer();
+ uint32_t rotation = private_data_->plane_transform_;
+ if (private_data_->rotation_type_ != RotationType::kDisplayRotation)
+ rotation = kIdentity;
+
+ target->SetTransform(rotation);
+
target->ResetDisplayFrame(private_data_->display_frame_);
if (private_data_->use_plane_scalar_) {
target->ResetSourceCrop(private_data_->source_crop_);
return false;
}
-DisplayPlaneState::ReValidationType DisplayPlaneState::IsRevalidationNeeded()
- const {
+uint32_t DisplayPlaneState::RevalidationType() const {
return re_validate_layer_;
}
-void DisplayPlaneState::RevalidationDone() {
- re_validate_layer_ = ReValidationType::kNone;
+void DisplayPlaneState::RevalidationDone(uint32_t validation_done) {
+ if (validation_done & ReValidationType::kScanout) {
+ re_validate_layer_ &= ~ReValidationType::kScanout;
+ }
+
+ if (validation_done & ReValidationType::kScalar) {
+ re_validate_layer_ &= ~ReValidationType::kScalar;
+ }
+
+ if (validation_done & ReValidationType::kRotation) {
+ re_validate_layer_ &= ~ReValidationType::kRotation;
+ }
}
bool DisplayPlaneState::CanSquash() const {
}
void DisplayPlaneState::ValidateReValidation() {
+ if (!private_data_->rect_updated_)
+ return;
+
+ if (private_data_->plane_transform_ != kIdentity &&
+ !private_data_->unsupported_siplay_rotation_) {
+ re_validate_layer_ |= ReValidationType::kRotation;
+ }
+
if (private_data_->source_layers_.size() == 1 &&
!(private_data_->type_ == DisplayPlanePrivateState::PlaneType::kVideo)) {
- re_validate_layer_ = ReValidationType::kScanout;
+ re_validate_layer_ |= ReValidationType::kScanout;
} else {
bool use_scalar = CanUseDisplayUpScaling();
if (private_data_->use_plane_scalar_ != use_scalar) {
- re_validate_layer_ = ReValidationType::kScalar;
+ re_validate_layer_ |= ReValidationType::kScalar;
}
}
}
return false;
}
- if (!private_data_->check_display_scalar_) {
+ if (!private_data_->rect_updated_) {
return private_data_->can_use_display_scalar_;
}
- private_data_->check_display_scalar_ = false;
const HwcRect<int> &target_display_frame = private_data_->display_frame_;
const HwcRect<float> &target_src_rect = private_data_->source_crop_;
}
}
+void DisplayPlaneState::SetRotationType(RotationType type, bool refresh) {
+ if (private_data_->rotation_type_ != type) {
+ private_data_->rotation_type_ = type;
+ if (refresh) {
+ refresh_needed_ = true;
+ RefreshSurfaces(NativeSurface::kFullClear);
+ }
+
+ uint32_t rotation = private_data_->plane_transform_;
+ if (type != RotationType::kDisplayRotation)
+ rotation = kIdentity;
+
+ for (NativeSurface *surface : private_data_->surfaces_) {
+ surface->SetTransform(rotation);
+ }
+ }
+}
+
+DisplayPlaneState::RotationType DisplayPlaneState::GetRotationType() const {
+ return private_data_->rotation_type_;
+}
+
+void DisplayPlaneState::PlaneRectUpdated() {
+ private_data_->rect_updated_ = true;
+}
+
} // namespace hwcomposer
class DisplayPlaneState {
public:
- enum class ReValidationType : int32_t {
- kNone, // No Revalidation Needed.
- kScanout, // Check if layer can be scanned out directly.
- kScalar // Check if layer can use plane scalar.
+ enum ReValidationType {
+ kNone = 0, // No Revalidation Needed.
+ kScanout = 1 << 0, // Check if layer can be scanned out directly.
+ kScalar = 1 << 1, // Check if layer can use plane scalar.
+ kRotation = 1 << 2 // Check if display transform can be supported.
};
+
+ enum class RotationType : int32_t {
+ kDisplayRotation, // Plane will be rotated during display composition.
+ kGPURotation // Plane will be rotated during 3D composition.
+ };
+
DisplayPlaneState() = default;
DisplayPlaneState(DisplayPlaneState &&rhs) = default;
DisplayPlaneState &operator=(DisplayPlaneState &&other) = default;
- DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer, uint32_t index);
+ DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer, uint32_t index,
+ uint32_t plane_transform);
// Copies plane state from state.
void CopyState(DisplayPlaneState &state);
// is needed for this plane.
bool NeedsOffScreenComposition();
- // Returns true if this plane needs to be re-validated
+ // Returns type of validation needed by the plane
// with current source layer. This will be the case
// when plane had multiple layers and they where
// removed leaving it with single layer now.
- ReValidationType IsRevalidationNeeded() const;
+ uint32_t RevalidationType() const;
// Plane has been revalidated by DisplayPlaneManager.
- void RevalidationDone();
+ void RevalidationDone(uint32_t validation_done);
// Call this to determine what kind of re-validation
// is needed by this plane for this frame.
// removed.
void RefreshSurfacesIfNeeded();
+ // Set if Plane rotation needs to be handled
+ // using GPU or Display.
+ void SetRotationType(RotationType type, bool refresh);
+
+ // Returns if Plane rotation is handled by
+ // GPU or Display. Return kNone in case
+ // plane is not rotated.
+ RotationType GetRotationType() const;
+
+ // Helper to inform that either Display Frame or
+ // Source rect of this plane has changed.
+ void PlaneRectUpdated();
+
private:
class DisplayPlanePrivateState {
public:
bool has_cursor_layer_ = false;
// Can benefit using display scalar.
bool can_use_display_scalar_ = false;
- // Retest for display scalar beenfit.
- bool check_display_scalar_ = true;
+ // Rects(Either Display Frame/Source Rect) have
+ // changed.
+ bool rect_updated_ = true;
+ // Display cannot support the required rotation.
+ bool unsupported_siplay_rotation_ = false;
// Any offscreen surfaces used by this
// plane.
std::vector<NativeSurface *> surfaces_;
PlaneType type_ = PlaneType::kNormal;
+ uint32_t plane_transform_ = kIdentity;
+ RotationType rotation_type_ = RotationType::kDisplayRotation;
};
bool recycled_surface_ = false;
bool surface_swapped_ = false;
bool refresh_needed_ = false;
- ReValidationType re_validate_layer_ = ReValidationType::kNone;
+ uint32_t re_validate_layer_ = ReValidationType::kNone;
std::shared_ptr<DisplayPlanePrivateState> private_data_;
};
return false;
}
- display_plane_manager_->SetDisplayRotation(plane_rotation_);
+ display_plane_manager_->SetDisplayTransform(plane_transform_);
ResetQueue();
vblank_handler_->SetPowerMode(kOff);
vblank_handler_->Init(gpu_fd_, pipe);
void DisplayQueue::RotateDisplay(HWCRotation rotation) {
switch (rotation) {
- case (kRotateNone):
- plane_rotation_ = kRotateNone;
- gl_rotation_ = kRotateNone;
+ case kRotate90:
+ plane_transform_ |= kTransform90;
break;
- case (kRotate90):
- plane_rotation_ = kRotateNone;
- gl_rotation_ = kRotate90;
+ case kRotate270:
+ plane_transform_ |= kTransform270;
break;
- case (kRotate180):
- plane_rotation_ = kRotate180;
- gl_rotation_ = kRotateNone;
- break;
- case (kRotate270):
- plane_rotation_ = kRotate270;
- gl_rotation_ = kRotateNone;
+ case kRotate180:
+ plane_transform_ |= kTransform180;
break;
default:
- plane_rotation_ = kRotateNone;
- gl_rotation_ = kRotateNone;
break;
}
- display_plane_manager_->SetDisplayRotation(plane_rotation_);
+ display_plane_manager_->SetDisplayTransform(plane_transform_);
}
void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
last_plane.ValidateReValidation();
- if (last_plane.IsRevalidationNeeded() ==
+ if (last_plane.RevalidationType() &
DisplayPlaneState::ReValidationType::kScanout) {
const std::vector<size_t>& source_layers =
last_plane.GetSourceLayers();
plane_validation = true;
} else if (source_layers.size() == 1) {
check_to_squash = true;
- last_plane.RevalidationDone();
+ last_plane.RevalidationDone(
+ DisplayPlaneState::ReValidationType::kScanout);
}
}
}
const std::vector<size_t>& source_layers = last_plane.GetSourceLayers();
size_t layers_size = source_layers.size();
+ HwcRect<int> display_frame = last_plane.GetDisplayFrame();
+ HwcRect<float> source_crop = last_plane.GetSourceCrop();
+
for (size_t i = 0; i < layers_size; i++) {
const size_t& source_index = source_layers.at(i);
const OverlayLayer& layer = layers.at(source_index);
if (update_rect) {
content_changed = true;
last_plane.ValidateReValidation();
- if (last_plane.IsRevalidationNeeded() !=
+ if (last_plane.RevalidationType() !=
DisplayPlaneState::ReValidationType::kNone) {
plane_validation = true;
}
+
+ bool rect_updated = true;
+ if ((last_plane.GetDisplayFrame() == display_frame) &&
+ (last_plane.GetSourceCrop() == source_crop)) {
+ rect_updated = false;
+ }
+
+ if (rect_updated) {
+ last_plane.PlaneRectUpdated();
+ }
}
}
overlay_layer->InitializeFromScaledHwcLayer(
layer, resource_manager_.get(), previous_layer, z_order, layer_index,
- display_frame, display_plane_manager_->GetHeight(), gl_rotation_,
+ display_frame, display_plane_manager_->GetHeight(), plane_transform_,
handle_constraints);
} else {
overlay_layer->InitializeFromHwcLayer(
layer, resource_manager_.get(), previous_layer, z_order, layer_index,
- display_plane_manager_->GetHeight(), gl_rotation_,
+ display_plane_manager_->GetHeight(), plane_transform_,
handle_constraints);
}
PhysicalDisplay* display_ = NULL;
SpinLock power_mode_lock_;
bool handle_display_initializations_ = true; // to disable hwclock thread.
- HWCRotation plane_rotation_ = kRotateNone;
- HWCRotation gl_rotation_ = kRotateNone;
+ uint32_t plane_transform_ = kIdentity;
SpinLock video_lock_;
bool requested_video_effect_ = false;
bool applied_video_effect_ = false;
previous_layer = &(in_flight_layers_.at(z_order));
}
- overlay_layer.InitializeFromHwcLayer(
- layer, resource_manager_.get(), previous_layer, z_order, layer_index,
- width_, kRotateNone, handle_constraints);
+ overlay_layer.InitializeFromHwcLayer(layer, resource_manager_.get(),
+ previous_layer, z_order, layer_index,
+ width_, kIdentity, handle_constraints);
index.emplace_back(z_order);
layers_rects.emplace_back(layer->GetDisplayFrame());
z_order++;
virtual bool IsSupportedFormat(uint32_t format) = 0;
/**
+ * API for querying if transform is supported by this
+ * plane.
+ */
+ virtual bool IsSupportedTransform(uint32_t transform) const = 0;
+
+ /**
* API for querying preferred Video format supported by this
* plane.
*/
bool DrmPlane::Property::Initialize(
uint32_t fd, const char* name,
- const ScopedDrmObjectPropertyPtr& plane_props) {
+ const ScopedDrmObjectPropertyPtr& plane_props, uint32_t* rotation) {
uint32_t count_props = plane_props->count_props;
for (uint32_t i = 0; i < count_props; i++) {
ScopedDrmPropertyPtr property(
drmModeGetProperty(fd, plane_props->props[i]));
if (property && !strcmp(property->name, name)) {
id = property->prop_id;
+ if (rotation) {
+ uint32_t temp = 0;
+ for (int enum_index = 0; enum_index < property->count_enums;
+ enum_index++) {
+ struct drm_mode_property_enum* penum = &(property->enums[enum_index]);
+ if (!strcmp(penum->name, "rotate-90")) {
+ temp |= DRM_MODE_ROTATE_90;
+ }
+ if (!strcmp(penum->name, "rotate-180"))
+ temp |= DRM_MODE_ROTATE_180;
+ else if (!strcmp(penum->name, "rotate-270"))
+ temp |= DRM_MODE_ROTATE_270;
+ else if (!strcmp(penum->name, "rotate-0"))
+ temp |= DRM_MODE_ROTATE_0;
+ }
+
+ *rotation = temp;
+ }
break;
}
}
if (!ret)
return false;
- ret = rotation_prop_.Initialize(gpu_fd, "rotation", plane_props);
+ ret = rotation_prop_.Initialize(gpu_fd, "rotation", plane_props, &rotation_);
if (!ret)
ETRACE("Could not get rotation property");
return false;
}
- return true;
+ return IsSupportedTransform(transform);
}
bool DrmPlane::IsSupportedFormat(uint32_t format) {
return false;
}
+bool DrmPlane::IsSupportedTransform(uint32_t transform) const {
+ if (transform & kTransform90) {
+ if (!(rotation_ & DRM_MODE_ROTATE_90)) {
+ return false;
+ }
+ } else if (transform & kTransform180) {
+ if (!(rotation_ & DRM_MODE_ROTATE_180)) {
+ return false;
+ }
+ } else if (transform & kTransform270) {
+ if (!(rotation_ & DRM_MODE_ROTATE_270)) {
+ return false;
+ }
+ } else {
+ if (!(rotation_ & DRM_MODE_ROTATE_0)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
uint32_t DrmPlane::GetPreferredVideoFormat() const {
return prefered_video_format_;
}
bool IsSupportedFormat(uint32_t format) override;
+ bool IsSupportedTransform(uint32_t transform) const override;
+
uint32_t GetPreferredVideoFormat() const override;
uint32_t GetPreferredFormat() const override;
struct Property {
Property();
bool Initialize(uint32_t fd, const char* name,
- const ScopedDrmObjectPropertyPtr& plane_properties);
+ const ScopedDrmObjectPropertyPtr& plane_properties,
+ uint32_t* rotation = NULL);
uint32_t id = 0;
};
int32_t kms_fence_ = 0;
uint32_t prefered_video_format_ = 0;
uint32_t prefered_format_ = 0;
+ uint32_t rotation_ = 0;
};
} // namespace hwcomposer