#include <drm_mode.h>
#include <hwctrace.h>
+#include <map>
+#include <vector>
#include "hwcutils.h"
+#include "nativebufferhandler.h"
#include "resourcemanager.h"
namespace hwcomposer {
void OverlayLayer::SetAcquireFence(int32_t acquire_fence) {
// Release any existing fence.
- if (imported_buffer_->acquire_fence_ > 0) {
- close(imported_buffer_->acquire_fence_);
- }
+ if (imported_buffer_.get()) {
+ if (imported_buffer_->acquire_fence_ > 0) {
+ close(imported_buffer_->acquire_fence_);
+ }
- imported_buffer_->acquire_fence_ = acquire_fence;
+ imported_buffer_->acquire_fence_ = acquire_fence;
+ }
}
int32_t OverlayLayer::GetAcquireFence() const {
- return imported_buffer_->acquire_fence_;
+ if (imported_buffer_.get()) {
+ return imported_buffer_->acquire_fence_;
+ } else
+ return -1;
}
int32_t OverlayLayer::ReleaseAcquireFence() const {
- int32_t fence = imported_buffer_->acquire_fence_;
- imported_buffer_->acquire_fence_ = -1;
- return fence;
+ if (imported_buffer_.get()) {
+ int32_t fence = imported_buffer_->acquire_fence_;
+ imported_buffer_->acquire_fence_ = -1;
+ return fence;
+ } else {
+ return -1;
+ }
}
OverlayBuffer* OverlayLayer::GetBuffer() const {
- if (imported_buffer_->buffer_.get() == NULL)
- ETRACE("hwc layer get NullBuffer");
- return imported_buffer_->buffer_.get();
+ if (imported_buffer_.get()) {
+ if (imported_buffer_->buffer_.get() == NULL)
+ ETRACE("hwc layer get NullBuffer");
+
+ return imported_buffer_->buffer_.get();
+ } else {
+ return NULL;
+ }
+}
+
+std::shared_ptr<OverlayBuffer>& OverlayLayer::GetSharedBuffer() const {
+ return imported_buffer_->buffer_;
}
void OverlayLayer::SetBuffer(HWCNativeHandle handle, int32_t acquire_fence,
ResourceManager* resource_manager,
- bool register_buffer) {
+ bool register_buffer,
+ FrameBufferManager* frame_buffer_manager) {
std::shared_ptr<OverlayBuffer> buffer(NULL);
- if (resource_manager) {
- buffer = resource_manager->FindCachedBuffer(GETNATIVEBUFFER(handle));
+ uint32_t id;
+
+ if (resource_manager && register_buffer) {
+ uint32_t gpu_fd = resource_manager->GetNativeBufferHandler()->GetFd();
+ id = GetNativeBuffer(gpu_fd, handle);
+ buffer = resource_manager->FindCachedBuffer(id);
}
if (buffer == NULL) {
buffer = OverlayBuffer::CreateOverlayBuffer();
buffer->InitializeFromNativeHandle(handle, resource_manager,
- register_buffer);
- if (register_buffer) {
- resource_manager->RegisterBuffer(GETNATIVEBUFFER(handle), buffer);
+ frame_buffer_manager);
+ if (resource_manager && register_buffer) {
+ resource_manager->RegisterBuffer(id, buffer);
}
+ } else {
+ buffer->SetOriginalHandle(handle);
}
+
+ buffer->SetDataSpace(dataspace_);
+
imported_buffer_.reset(new ImportedBuffer(buffer, acquire_fence));
- if (!register_buffer) {
- ValidateForOverlayUsage();
- }
+ ValidateForOverlayUsage();
}
void OverlayLayer::SetBlending(HWCBlending blending) {
display_frame_width_ = display_frame.right - display_frame.left;
display_frame_height_ = display_frame.bottom - display_frame.top;
display_frame_ = display_frame;
- surface_damage_ = display_frame;
+}
+
+void OverlayLayer::SetTransform(uint32_t transform) {
+ plane_transform_ = transform;
+ transform_ = transform;
}
void OverlayLayer::ValidateTransform(uint32_t transform,
uint32_t display_transform) {
- if (transform & kTransform90) {
- if (transform & kReflectX) {
- plane_transform_ |= kReflectX;
- }
-
- if (transform & kReflectY) {
- plane_transform_ |= kReflectY;
- }
-
- switch (display_transform) {
- case kRotate90:
- plane_transform_ |= kTransform180;
- break;
- case kRotate180:
- plane_transform_ |= kTransform270;
- break;
- case kRotateNone:
- plane_transform_ |= kTransform90;
- break;
- default:
- break;
- }
- } else if (transform & kTransform180) {
- switch (display_transform) {
- case kRotate90:
- plane_transform_ |= kTransform270;
- break;
- case kRotate270:
- plane_transform_ |= kTransform90;
- break;
- case kRotateNone:
- plane_transform_ |= kTransform180;
- break;
- default:
- break;
- }
- } else if (transform & kTransform270) {
- switch (display_transform) {
- case kRotate270:
- plane_transform_ |= kTransform180;
- break;
- case kRotate180:
- plane_transform_ |= kTransform90;
- break;
- case kRotateNone:
- plane_transform_ |= kTransform270;
- break;
- default:
- break;
- }
+ std::map<int, int> tmap = {{kIdentity, 0},
+ {kTransform90, 1},
+ {kTransform180, 2},
+ {kTransform270, 3}};
+ std::vector<int> inv_tmap = {kIdentity, kTransform90, kTransform180,
+ kTransform270};
+
+ int mdisplay_transform = display_transform;
+ int mtransform =
+ transform & (kIdentity | kTransform90 | kTransform180 | kTransform270);
+
+ if (tmap.find(mtransform) != tmap.end()) {
+ mtransform = tmap[mtransform];
} else {
- if (display_transform == kRotate90) {
- if (transform & kReflectX) {
- plane_transform_ |= kReflectX;
- }
-
- if (transform & kReflectY) {
- plane_transform_ |= kReflectY;
- }
-
- plane_transform_ |= kTransform90;
- } else {
- switch (display_transform) {
- case kRotate270:
- plane_transform_ |= kTransform270;
- break;
- case kRotate180:
- plane_transform_ |= kReflectY;
- break;
- default:
- break;
- }
- }
+ // reaching here indicates that transform is
+ // is an OR of multiple values
+ // Assign Identity in this case
+ mtransform = kIdentity;
}
-}
-void OverlayLayer::UpdateSurfaceDamage(HwcLayer* layer) {
- if (!gpu_rendered_) {
- surface_damage_ = display_frame_;
- return;
+ if (tmap.find(mdisplay_transform) != tmap.end()) {
+ mdisplay_transform = tmap[mdisplay_transform];
+ } else {
+ mdisplay_transform = kIdentity;
}
- if ((state_ & kClearSurface) || (state_ & kDimensionsChanged) ||
- (transform_ != kIdentity)) {
- surface_damage_ = display_frame_;
- return;
- }
+ // The elements {0, 1, 2, 3} form a circulant matrix under mod 4 arithmetic
+ mtransform = (mtransform + mdisplay_transform) % 4;
+ mtransform = inv_tmap[mtransform];
+ plane_transform_ = mtransform;
- surface_damage_ = layer->GetSurfaceDamage();
+ if (plane_transform_ & kTransform90) {
+ if (transform & kReflectX)
+ plane_transform_ |= kReflectX;
+
+ if (transform & kReflectY)
+ plane_transform_ |= kReflectY;
+ }
}
void OverlayLayer::InitializeState(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,
+ FrameBufferManager* frame_buffer_manager) {
transform_ = layer->GetTransform();
if (rotation != kRotateNone) {
ValidateTransform(layer->GetTransform(), rotation);
- // Remove this in case we enable support in future
- // to apply display rotation at pipe level.
- transform_ = plane_transform_;
} else {
plane_transform_ = transform_;
}
source_crop_width_ = layer->GetSourceCropWidth();
source_crop_height_ = layer->GetSourceCropHeight();
source_crop_ = layer->GetSourceCrop();
+ dataspace_ = layer->GetDataSpace();
blending_ = layer->GetBlending();
- SetBuffer(layer->GetNativeHandle(), layer->GetAcquireFence(),
- resource_manager, true);
- ValidateForOverlayUsage();
- if (previous_layer) {
- ValidatePreviousFrameState(previous_layer, layer);
+ surface_damage_ = layer->GetLayerDamage();
+
+ solid_color_ = layer->GetSolidColor();
+
+ if (previous_layer && layer->HasZorderChanged()) {
+ if (previous_layer->actual_composition_ == kGpu) {
+ CalculateRect(previous_layer->display_frame_, surface_damage_);
+ bool force_partial_clear = true;
+ // We can skip Clear in case display frame, transforms are same.
+ if (previous_layer->display_frame_ == display_frame_ &&
+ transform_ == previous_layer->transform_ &&
+ plane_transform_ == previous_layer->plane_transform_) {
+ force_partial_clear = false;
+ }
+
+ if (force_partial_clear) {
+ state_ |= kForcePartialClear;
+ }
+ } else if (!layer->IsCursorLayer()) {
+ state_ |= kNeedsReValidation;
+ }
+ }
+
+ if (layer->GetNativeHandle()) {
+ SetBuffer(layer->GetNativeHandle(), layer->GetAcquireFence(),
+ resource_manager, true, frame_buffer_manager);
+ } else if (Composition_SolidColor == layer->GetLayerCompositionType()) {
+ type_ = kLayerSolidColor;
+ source_crop_width_ = layer->GetDisplayFrameWidth();
+ source_crop_height_ = layer->GetDisplayFrameHeight();
+ source_crop_.left = source_crop_.top = 0;
+ source_crop_.right = source_crop_width_;
+ source_crop_.top = source_crop_height_;
+ imported_buffer_.reset(NULL);
+ } else {
+ ETRACE(
+ "HWC don't support a layer with no buffer handle except in SolidColor "
+ "type");
}
- if (layer->HasContentAttributesChanged() ||
- layer->HasLayerAttributesChanged() || !layer->IsValidated()) {
- state_ |= kClearSurface;
- state_ |= kLayerContentChanged;
+ if (!surface_damage_.empty()) {
+ if (type_ == kLayerCursor) {
+ const std::shared_ptr<OverlayBuffer>& buffer = imported_buffer_->buffer_;
+ surface_damage_.right = surface_damage_.left + buffer->GetWidth();
+ surface_damage_.bottom = surface_damage_.top + buffer->GetHeight();
+ }
}
if (!handle_constraints) {
- UpdateSurfaceDamage(layer);
+ if (previous_layer) {
+ ValidatePreviousFrameState(previous_layer, layer);
+ }
return;
}
display_frame_.right = right_source_constraint;
}
+ // Handle case where we might be using logical and Mosaic together.
display_frame_.left =
(display_frame_.left - left_source_constraint) + left_constraint;
display_frame_.right =
(display_frame_.right - left_source_constraint) + left_constraint;
+ IMOSAICDISPLAYTRACE(
+ "display_frame_ %d %d %d %d left_source_constraint: %d "
+ "left_constraint: %d \n",
+ display_frame_.left, display_frame_.right, display_frame_.top,
+ display_frame_.bottom, left_source_constraint, left_constraint);
display_frame_.bottom =
std::min(max_height, static_cast<uint32_t>(display_frame_.bottom));
display_frame_width_ = display_frame_.right - display_frame_.left;
display_frame_height_ = display_frame_.bottom - display_frame_.top;
- UpdateSurfaceDamage(layer);
- if (gpu_rendered_) {
- // If viewport and layer doesn't interact we can avoid re-rendering
- // this layer.
- if (AnalyseOverlap(surface_damage_, display_frame_) != kOutside) {
- surface_damage_.left =
- std::max(surface_damage_.left, display_frame_.left);
- surface_damage_.right =
- std::min(surface_damage_.right, display_frame_.right);
- surface_damage_.top = std::max(surface_damage_.top, display_frame_.top);
- surface_damage_.bottom =
- std::min(surface_damage_.bottom, display_frame_.bottom);
- } else {
- surface_damage_ = HwcRect<int>(0, 0, 0, 0);
- }
+ if ((surface_damage_.left < display_frame_.left) &&
+ (surface_damage_.right > display_frame_.left)) {
+ surface_damage_.left = display_frame_.left;
+ }
+
+ if (surface_damage_.right > display_frame_.right) {
+ surface_damage_.right = display_frame_.right;
+ }
+
+ if (AnalyseOverlap(surface_damage_, display_frame_) != kOutside) {
+ surface_damage_.bottom =
+ std::min(surface_damage_.bottom, display_frame_.bottom);
+ surface_damage_.right =
+ std::min(surface_damage_.right, display_frame_.right);
+ surface_damage_.left =
+ std::max(surface_damage_.left, display_frame_.left);
+ } else {
+ surface_damage_.reset();
}
+ IMOSAICDISPLAYTRACE(
+ "surface_damage_ %d %d %d %d left_source_constraint: %d "
+ "left_constraint: %d \n",
+ surface_damage_.left, surface_damage_.right, surface_damage_.top,
+ surface_damage_.bottom, left_source_constraint, left_constraint);
// split the source in proportion of frame rect offset for sub displays as:
// 1. the original source size may be different with the original frame
source_crop_height_ = static_cast<int>(ceilf(source_crop_.bottom) -
static_cast<int>(source_crop_.top));
}
+
+ if (previous_layer) {
+ ValidatePreviousFrameState(previous_layer, layer);
+ }
}
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,
+ FrameBufferManager* frame_buffer_manager) {
display_frame_width_ = layer->GetDisplayFrameWidth();
display_frame_height_ = layer->GetDisplayFrameHeight();
display_frame_ = layer->GetDisplayFrame();
InitializeState(layer, resource_manager, previous_layer, z_order, layer_index,
- max_height, rotation, handle_constraints);
+ max_height, rotation, handle_constraints,
+ frame_buffer_manager);
}
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, FrameBufferManager* frame_buffer_manager) {
SetDisplayFrame(display_frame);
InitializeState(layer, resource_manager, previous_layer, z_order, layer_index,
- max_height, rotation, handle_constraints);
+ max_height, rotation, handle_constraints,
+ frame_buffer_manager);
}
void OverlayLayer::ValidatePreviousFrameState(OverlayLayer* rhs,
HwcLayer* layer) {
- OverlayBuffer* buffer = imported_buffer_->buffer_.get();
- if (buffer->GetFormat() != rhs->imported_buffer_->buffer_->GetFormat())
- return;
+ OverlayBuffer* buffer = NULL;
+ if (imported_buffer_.get())
+ buffer = imported_buffer_->buffer_.get();
+
+ supported_composition_ = rhs->supported_composition_;
+ actual_composition_ = rhs->actual_composition_;
bool content_changed = false;
bool rect_changed = layer->HasDisplayRectChanged();
state_ |= kSourceRectChanged;
// We expect cursor plane to support alpha always.
- if (rhs->gpu_rendered_ || (type_ == kLayerCursor)) {
- content_changed = rect_changed || source_rect_changed;
+ if ((actual_composition_ & kGpu) || (type_ == kLayerCursor) ||
+ (type_ == kLayerSolidColor)) {
+ if (actual_composition_ & kGpu) {
+ content_changed = rect_changed || source_rect_changed;
+ // This layer has replaced an existing layer, let's make sure
+ // we re-draw this and previous layer regions.
+ if (!layer->IsValidated()) {
+ content_changed = true;
+ CalculateRect(rhs->display_frame_, surface_damage_);
+ } else if (!content_changed) {
+ if ((buffer && rhs->imported_buffer_.get() &&
+ (buffer->GetFormat() !=
+ rhs->imported_buffer_->buffer_->GetFormat())) ||
+ (alpha_ != rhs->alpha_) || (blending_ != rhs->blending_) ||
+ (transform_ != rhs->transform_)) {
+ content_changed = true;
+ }
+ }
+ } else if (type_ == kLayerCursor) {
+ if (layer->HasLayerAttributesChanged()) {
+ state_ |= kNeedsReValidation;
+ }
+ }
} else {
+ // Ensure the buffer can be supported by display for direct
+ // scanout.
+ if (!rhs->imported_buffer_.get()) {
+ state_ |= kNeedsReValidation;
+ return;
+ } else if (buffer && (buffer->GetFormat() !=
+ rhs->imported_buffer_->buffer_->GetFormat())) {
+ state_ |= kNeedsReValidation;
+ return;
+ }
+
// If previous layer was opaque and we have alpha now,
// let's mark this layer for re-validation. Plane
// supporting XRGB format might not necessarily support
// transparent planes. We assume plane supporting
// ARGB will support XRGB.
- if ((rhs->alpha_ == 0xff) && (alpha_ != rhs->alpha_))
+ if ((rhs->alpha_ == 0xff) && (alpha_ != rhs->alpha_)) {
+ state_ |= kNeedsReValidation;
return;
+ }
- if (blending_ != rhs->blending_)
+ if (blending_ != rhs->blending_) {
+ state_ |= kNeedsReValidation;
return;
+ }
if (rect_changed || layer->HasLayerAttributesChanged()) {
- if (layer->IsValidated()) {
- return;
- }
-
- if (rhs->transform_ != transform_) {
- return;
- }
-
- if ((rhs->display_frame_.left != display_frame_.left) ||
- (rhs->display_frame_.right != display_frame_.right) ||
- (rhs->display_frame_.top != display_frame_.top) ||
- (rhs->display_frame_.bottom != display_frame_.bottom)) {
- return;
- }
+ state_ |= kNeedsReValidation;
+ return;
}
if (source_rect_changed) {
// shouldn't impact the plane composition results.
if ((source_crop_width_ != rhs->source_crop_width_) ||
(source_crop_height_ != rhs->source_crop_height_)) {
+ state_ |= kNeedsReValidation;
return;
}
}
}
- state_ &= ~kLayerAttributesChanged;
- gpu_rendered_ = rhs->gpu_rendered_;
-
if (!rect_changed) {
state_ &= ~kDimensionsChanged;
}
- if (!layer->HasVisibleRegionChanged() &&
- !layer->HasSurfaceDamageRegionChanged() &&
- !layer->HasLayerContentChanged() && !content_changed) {
+ if (!layer->HasVisibleRegionChanged() && !content_changed &&
+ surface_damage_.empty() && !layer->HasLayerContentChanged() &&
+ !(state_ & kNeedsReValidation)) {
state_ &= ~kLayerContentChanged;
}
}
void OverlayLayer::ValidateForOverlayUsage() {
const std::shared_ptr<OverlayBuffer>& buffer = imported_buffer_->buffer_;
- if (buffer->GetUsage() & kLayerCursor) {
- type_ = kLayerCursor;
- } else if (buffer->IsVideoBuffer()) {
- type_ = kLayerVideo;
+ type_ = buffer->GetUsage();
+}
+
+void OverlayLayer::CloneLayer(const OverlayLayer* layer,
+ const HwcRect<int>& display_frame,
+ ResourceManager* resource_manager,
+ uint32_t z_order,
+ FrameBufferManager* frame_buffer_manager) {
+ int32_t fence = layer->GetAcquireFence();
+ int32_t aquire_fence = 0;
+ if (fence > 0) {
+ aquire_fence = dup(fence);
}
+ SetDisplayFrame(display_frame);
+ SetSourceCrop(layer->GetSourceCrop());
+ SetBuffer(layer->GetBuffer()->GetOriginalHandle(), aquire_fence,
+ resource_manager, true, frame_buffer_manager);
+ ValidateForOverlayUsage();
+ surface_damage_ = layer->GetSurfaceDamage();
+ transform_ = layer->transform_;
+ plane_transform_ = layer->plane_transform_;
+ alpha_ = layer->alpha_;
+ layer_index_ = z_order;
+ z_order_ = z_order;
+ blending_ = layer->blending_;
+ solid_color_ = layer->solid_color_;
}
void OverlayLayer::Dump() {
DUMPTRACE("Transform: kReflectX.");
if (transform_ & kReflectY)
DUMPTRACE("Transform: kReflectY.");
- if (transform_ & kReflectY)
- DUMPTRACE("Transform: kReflectY.");
+ if (transform_ & kTransform90)
+ DUMPTRACE("Transform: kTransform90.");
else if (transform_ & kTransform180)
DUMPTRACE("Transform: kTransform180.");
else if (transform_ & kTransform270)
DUMPTRACE("SourceHeight: %d", source_crop_height_);
DUMPTRACE("DstWidth: %d", display_frame_width_);
DUMPTRACE("DstHeight: %d", display_frame_height_);
- DUMPTRACE("AquireFence: %d", imported_buffer_->acquire_fence_);
+ DUMPTRACE("Source crop %s", StringifyRect(source_crop_).c_str());
+ DUMPTRACE("Display frame %s", StringifyRect(display_frame_).c_str());
+ DUMPTRACE("Surface Damage %s", StringifyRect(surface_damage_).c_str());
+ if (imported_buffer_)
+ DUMPTRACE("AquireFence: %d", imported_buffer_->acquire_fence_);
imported_buffer_->buffer_->Dump();
}