#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, HwcLayer* layer) {
+ bool register_buffer,
+ FrameBufferManager* frame_buffer_manager) {
std::shared_ptr<OverlayBuffer> buffer(NULL);
- // FIXME: Enable cache again.
- /*if (resource_manager && register_buffer) {
- 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();
- bool is_cursor_layer = false;
- if (layer) {
- is_cursor_layer = layer->IsCursorLayer();
- }
buffer->InitializeFromNativeHandle(handle, resource_manager,
- is_cursor_layer);
- 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);
}
- if (register_buffer && handle->is_raw_pixel_ && !surface_damage_.empty()) {
- buffer->UpdateRawPixelBackingStore(handle->pixel_memory_);
- state_ |= kRawPixelDataChanged;
- }
+ buffer->SetDataSpace(dataspace_);
imported_buffer_.reset(new ImportedBuffer(buffer, acquire_fence));
ValidateForOverlayUsage();
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) {
void OverlayLayer::ValidateTransform(uint32_t transform,
uint32_t display_transform) {
- if (transform & kTransform90) {
- switch (display_transform) {
- case HWCTransform::kTransform90:
- plane_transform_ |= kTransform180;
- break;
- case HWCTransform::kTransform180:
- plane_transform_ |= kTransform270;
- break;
- case HWCTransform::kIdentity:
- plane_transform_ |= kTransform90;
- if (transform & kReflectX) {
- plane_transform_ |= kReflectX;
- }
+ 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 {
+ // reaching here indicates that transform is
+ // is an OR of multiple values
+ // Assign Identity in this case
+ mtransform = kIdentity;
+ }
- if (transform & kReflectY) {
- plane_transform_ |= kReflectY;
- }
- break;
- default:
- break;
- }
- } else if (transform & kTransform180) {
- switch (display_transform) {
- case HWCTransform::kTransform90:
- plane_transform_ |= kTransform270;
- break;
- case HWCTransform::kTransform270:
- plane_transform_ |= kTransform90;
- break;
- case HWCTransform::kIdentity:
- plane_transform_ |= kTransform180;
- break;
- default:
- break;
- }
- } else if (transform & kTransform270) {
- switch (display_transform) {
- case HWCTransform::kTransform270:
- plane_transform_ |= kTransform180;
- break;
- case HWCTransform::kTransform180:
- plane_transform_ |= kTransform90;
- break;
- case HWCTransform::kIdentity:
- plane_transform_ |= kTransform270;
- break;
- default:
- break;
- }
+ if (tmap.find(mdisplay_transform) != tmap.end()) {
+ mdisplay_transform = tmap[mdisplay_transform];
} else {
- if (display_transform & HWCTransform::kTransform90) {
- if (transform & kReflectX) {
- plane_transform_ |= kReflectX;
- }
+ mdisplay_transform = kIdentity;
+ }
- if (transform & kReflectY) {
- plane_transform_ |= kReflectY;
- }
+ // 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;
- plane_transform_ |= kTransform90;
- } else {
- switch (display_transform) {
- case HWCTransform::kTransform270:
- plane_transform_ |= kTransform270;
- break;
- case HWCTransform::kTransform180:
- plane_transform_ |= kTransform180;
- break;
- default:
- break;
- }
- }
+ if (plane_transform_ & kTransform90) {
+ if (transform & kReflectX)
+ plane_transform_ |= kReflectX;
+
+ if (transform & kReflectY)
+ plane_transform_ |= kReflectY;
}
}
OverlayLayer* previous_layer,
uint32_t z_order, uint32_t layer_index,
uint32_t max_height, uint32_t rotation,
- bool handle_constraints) {
+ bool handle_constraints,
+ FrameBufferManager* frame_buffer_manager) {
transform_ = layer->GetTransform();
if (rotation != kRotateNone) {
ValidateTransform(layer->GetTransform(), rotation);
source_crop_width_ = layer->GetSourceCropWidth();
source_crop_height_ = layer->GetSourceCropHeight();
source_crop_ = layer->GetSourceCrop();
+ dataspace_ = layer->GetDataSpace();
blending_ = layer->GetBlending();
- if (!layer->IsCursorLayer() && layer->HasZorderChanged() &&
- (!previous_layer ||
- (previous_layer && (previous_layer->z_order_ != z_order)))) {
- state_ |= kLayerOrderChanged;
+ 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;
+ }
}
- surface_damage_ = layer->GetLayerDamage();
- SetBuffer(layer->GetNativeHandle(), layer->GetAcquireFence(),
- resource_manager, true, layer);
+ 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 (!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) {
if (previous_layer) {
display_frame_width_ = display_frame_.right - display_frame_.left;
display_frame_height_ = display_frame_.bottom - display_frame_.top;
+ 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);
void OverlayLayer::InitializeFromHwcLayer(
HwcLayer* layer, ResourceManager* resource_manager,
OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
- uint32_t max_height, uint32_t 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, uint32_t rotation,
- bool handle_constraints) {
+ 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();
+ OverlayBuffer* buffer = NULL;
+ if (imported_buffer_.get())
+ buffer = imported_buffer_->buffer_.get();
+
supported_composition_ = rhs->supported_composition_;
actual_composition_ = rhs->actual_composition_;
state_ |= kSourceRectChanged;
// We expect cursor plane to support alpha always.
- if ((actual_composition_ & kGpu) || (type_ == kLayerCursor)) {
+ 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
content_changed = true;
CalculateRect(rhs->display_frame_, surface_damage_);
} else if (!content_changed) {
- if ((buffer->GetFormat() !=
- rhs->imported_buffer_->buffer_->GetFormat()) ||
+ 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 {
// Ensure the buffer can be supported by display for direct
// scanout.
- if (buffer->GetFormat() != rhs->imported_buffer_->buffer_->GetFormat()) {
+ if (!rhs->imported_buffer_.get()) {
+ state_ |= kNeedsReValidation;
+ return;
+ } else if (buffer && (buffer->GetFormat() !=
+ rhs->imported_buffer_->buffer_->GetFormat())) {
state_ |= kNeedsReValidation;
return;
}
if (!layer->HasVisibleRegionChanged() && !content_changed &&
surface_damage_.empty() && !layer->HasLayerContentChanged() &&
- !(state_ & kNeedsReValidation) && !(state_ & kRawPixelDataChanged)) {
+ !(state_ & kNeedsReValidation)) {
state_ &= ~kLayerContentChanged;
}
}
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("OverlayLayer Information Starts. -------------");
switch (blending_) {
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();
}