} // anonymous namespace
-// HardwareComposer static data;
-constexpr size_t HardwareComposer::kMaxHardwareLayers;
-
HardwareComposer::HardwareComposer()
: initialized_(false), request_display_callback_(nullptr) {}
}
bool HardwareComposer::Initialize(
- Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
+ Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) {
if (initialized_) {
ALOGE("HardwareComposer::Initialize: already initialized.");
return false;
HWC::Error error = HWC::Error::None;
Hwc2::Config config;
- error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+ error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
if (error != HWC::Error::None) {
ALOGE("HardwareComposer: Failed to get current display config : %d",
return false;
}
- error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config,
+ error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config,
&native_display_metrics_);
if (error != HWC::Error::None) {
display_transform_ = HWC_TRANSFORM_NONE;
display_metrics_ = native_display_metrics_;
+ // Setup the display metrics used by all Layer instances.
+ Layer::SetDisplayMetrics(native_display_metrics_);
+
post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
LOG_ALWAYS_FATAL_IF(
!post_thread_event_fd_,
}
void HardwareComposer::OnPostThreadResumed() {
- hidl_.reset(new Hwc2::Composer(false));
- hidl_callback_ = new ComposerCallback;
- hidl_->registerCallback(hidl_callback_);
+ composer_.reset(new Hwc2::Composer(false));
+ composer_callback_ = new ComposerCallback;
+ composer_->registerCallback(composer_callback_);
+ Layer::SetComposer(composer_.get());
EnableVsync(true);
void HardwareComposer::OnPostThreadPaused() {
retire_fence_fds_.clear();
- display_surfaces_.clear();
-
- for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
- layers_[i].Reset();
- }
- active_layer_count_ = 0;
+ layers_.clear();
- if (hidl_) {
+ if (composer_) {
EnableVsync(false);
}
- hidl_callback_ = nullptr;
- hidl_.reset(nullptr);
+ composer_callback_ = nullptr;
+ composer_.reset(nullptr);
+ Layer::SetComposer(nullptr);
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
uint32_t num_types;
uint32_t num_requests;
HWC::Error error =
- hidl_->validateDisplay(display, &num_types, &num_requests);
+ composer_->validateDisplay(display, &num_types, &num_requests);
if (error == HWC2_ERROR_HAS_CHANGES) {
// TODO(skiazyk): We might need to inspect the requested changes first, but
// so far it seems like we shouldn't ever hit a bad state.
// error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
// display);
- error = hidl_->acceptDisplayChanges(display);
+ error = composer_->acceptDisplayChanges(display);
}
return error;
}
HWC::Error HardwareComposer::EnableVsync(bool enabled) {
- return hidl_->setVsyncEnabled(
+ return composer_->setVsyncEnabled(
HWC_DISPLAY_PRIMARY,
(Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
: HWC2_VSYNC_DISABLE));
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
int32_t present_fence;
- HWC::Error error = hidl_->presentDisplay(display, &present_fence);
+ HWC::Error error = composer_->presentDisplay(display, &present_fence);
// According to the documentation, this fence is signaled at the time of
// vsync/DMA for physical displays.
return error;
}
-HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl,
+HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* composer,
hwc2_display_t display,
hwc2_config_t config,
hwc2_attribute_t attribute,
int32_t* out_value) const {
- return hidl->getDisplayAttribute(
+ return composer->getDisplayAttribute(
display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
}
HWC::Error HardwareComposer::GetDisplayMetrics(
- Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config,
+ Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const {
HWC::Error error;
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_WIDTH,
&out_metrics->width);
if (error != HWC::Error::None) {
ALOGE(
return error;
}
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_HEIGHT,
&out_metrics->height);
if (error != HWC::Error::None) {
ALOGE(
return error;
}
- error = GetDisplayAttribute(hidl, display, config,
+ error = GetDisplayAttribute(composer, display, config,
HWC2_ATTRIBUTE_VSYNC_PERIOD,
&out_metrics->vsync_period_ns);
if (error != HWC::Error::None) {
return error;
}
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_X,
&out_metrics->dpi.x);
if (error != HWC::Error::None) {
ALOGE(
return error;
}
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_Y,
&out_metrics->dpi.y);
if (error != HWC::Error::None) {
ALOGE(
<< std::endl;
stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
- stream << "Active layers: " << active_layer_count_ << std::endl;
+ stream << "Active layers: " << layers_.size() << std::endl;
stream << std::endl;
- for (size_t i = 0; i < active_layer_count_; i++) {
+ for (size_t i = 0; i < layers_.size(); i++) {
stream << "Layer " << i << ":";
stream << " type=" << layers_[i].GetCompositionType().to_string();
stream << " surface_id=" << layers_[i].GetSurfaceId();
if (post_thread_resumed_) {
stream << "Hardware Composer Debug Info:" << std::endl;
- stream << hidl_->dumpDebugInfo();
+ stream << composer_->dumpDebugInfo();
}
return stream.str();
ATRACE_NAME("HardwareComposer::PostLayers");
// Setup the hardware composer layers with current buffers.
- for (size_t i = 0; i < active_layer_count_; i++) {
- layers_[i].Prepare();
+ for (auto& layer : layers_) {
+ layer.Prepare();
}
HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
"Warning: dropping a frame to catch up with HWC (pending = %zd)",
retire_fence_fds_.size());
- for (size_t i = 0; i < active_layer_count_; i++) {
- layers_[i].Drop();
+ for (auto& layer : layers_) {
+ layer.Drop();
}
return;
} else {
}
#if TRACE > 1
- for (size_t i = 0; i < active_layer_count_; i++) {
+ for (size_t i = 0; i < layers_.size(); i++) {
ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
i, layers_[i].GetBufferId(),
layers_[i].GetCompositionType().to_string().c_str());
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
- &out_fences);
+ error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+ &out_fences);
ALOGE_IF(error != HWC::Error::None,
"HardwareComposer::PostLayers: Failed to get release fences: %s",
error.to_string().c_str());
- // Perform post-frame bookkeeping. Unused layers are a no-op.
+ // Perform post-frame bookkeeping.
uint32_t num_elements = out_layers.size();
for (size_t i = 0; i < num_elements; ++i) {
- for (size_t j = 0; j < active_layer_count_; ++j) {
- if (layers_[j].GetLayerHandle() == out_layers[i]) {
- layers_[j].Finish(out_fences[i]);
+ for (auto& layer : layers_) {
+ if (layer.GetLayerHandle() == out_layers[i]) {
+ layer.Finish(out_fences[i]);
}
}
}
// vsync already passed since the last call, returns the latest vsync timestamp
// instead of blocking.
int HardwareComposer::WaitForVSync(int64_t* timestamp) {
- int error = PostThreadPollInterruptible(
- hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000);
+ int error = PostThreadPollInterruptible(composer_callback_->GetVsyncEventFd(),
+ POLLIN, /*timeout_ms*/ 1000);
if (error == kPostThreadInterrupted || error < 0) {
return error;
} else {
- *timestamp = hidl_callback_->GetVsyncTime();
+ *timestamp = composer_callback_->GetVsyncTime();
return 0;
}
}
ATRACE_NAME("UpdateLayerConfig_HwLayers");
- display_surfaces_.clear();
+ // Sort the new direct surface list by z-order to determine the relative order
+ // of the surfaces. This relative order is used for the HWC z-order value to
+ // insulate VrFlinger and HWC z-order semantics from each other.
+ std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
+ return a->z_order() < b->z_order();
+ });
- Layer* target_layer;
- size_t layer_index;
- for (layer_index = 0;
- layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
- layer_index++) {
+ // Prepare a new layer stack, pulling in layers from the previous
+ // layer stack that are still active and updating their attributes.
+ std::vector<Layer> layers;
+ size_t layer_index = 0;
+ for (const auto& surface : surfaces) {
// The bottom layer is opaque, other layers blend.
HWC::BlendMode blending =
layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
- layers_[layer_index].Setup(surfaces[layer_index], native_display_metrics_,
- hidl_.get(), blending,
- display_transform_, HWC::Composition::Device,
- layer_index);
- display_surfaces_.push_back(surfaces[layer_index]);
- }
- // Clear unused layers.
- for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
- layers_[i].Reset();
+ // Try to find a layer for this surface in the set of active layers.
+ auto search =
+ std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
+ const bool found = search != layers_.end() &&
+ search->GetSurfaceId() == surface->surface_id();
+ if (found) {
+ // Update the attributes of the layer that may have changed.
+ search->SetBlending(blending);
+ search->SetZOrder(layer_index); // Relative z-order.
+
+ // Move the existing layer to the new layer set and remove the empty layer
+ // object from the current set.
+ layers.push_back(std::move(*search));
+ layers_.erase(search);
+ } else {
+ // Insert a layer for the new surface.
+ layers.emplace_back(surface, blending, display_transform_,
+ HWC::Composition::Device, layer_index);
+ }
- active_layer_count_ = layer_index;
- ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
- active_layer_count_);
+ ALOGI_IF(
+ TRACE,
+ "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
+ layer_index, layers[layer_index].GetSurfaceId());
+
+ layer_index++;
+ }
+
+ // Sort the new layer stack by ascending surface id.
+ std::sort(layers.begin(), layers.end());
- // Any surfaces left over could not be assigned a hardware layer and will
- // not be displayed.
- ALOGW_IF(surfaces.size() != display_surfaces_.size(),
- "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
- "pending_surfaces=%zu display_surfaces=%zu",
- surfaces.size(), display_surfaces_.size());
+ // Replace the previous layer set with the new layer set. The destructor of
+ // the previous set will clean up the remaining Layers that are not moved to
+ // the new layer set.
+ layers_ = std::move(layers);
+ ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
+ layers_.size());
return true;
}
return return_val;
}
+Hwc2::Composer* Layer::composer_{nullptr};
+HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
+
void Layer::Reset() {
- if (hidl_ != nullptr && hardware_composer_layer_) {
- hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+ if (hardware_composer_layer_) {
+ composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
hardware_composer_layer_ = 0;
}
- hidl_ = nullptr;
z_order_ = 0;
blending_ = HWC::BlendMode::None;
transform_ = HWC::Transform::None;
source_ = EmptyVariant{};
acquire_fence_.Close();
surface_rect_functions_applied_ = false;
+ pending_visibility_settings_ = true;
}
-void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
- const HWCDisplayMetrics& display_metrics,
- Hwc2::Composer* hidl, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order) {
- Reset();
- hidl_ = hidl;
- z_order_ = z_order;
- blending_ = blending;
- transform_ = transform;
- composition_type_ = HWC::Composition::Invalid;
- target_composition_type_ = composition_type;
- source_ = SourceSurface{surface};
- CommonLayerSetup(display_metrics);
+Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_order)
+ : z_order_{z_order},
+ blending_{blending},
+ transform_{transform},
+ target_composition_type_{composition_type},
+ source_{SourceSurface{surface}} {
+ CommonLayerSetup();
}
-void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
- const HWCDisplayMetrics& display_metrics,
- Hwc2::Composer* hidl, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order) {
- Reset();
- hidl_ = hidl;
- z_order_ = z_order;
- blending_ = blending;
- transform_ = transform;
- composition_type_ = HWC::Composition::Invalid;
- target_composition_type_ = composition_type;
- source_ = SourceBuffer{buffer};
- CommonLayerSetup(display_metrics);
+Layer::Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order)
+ : z_order_{z_order},
+ blending_{blending},
+ transform_{transform},
+ target_composition_type_{composition_type},
+ source_{SourceBuffer{buffer}} {
+ CommonLayerSetup();
+}
+
+Layer::~Layer() { Reset(); }
+
+Layer::Layer(Layer&& other) { *this = std::move(other); }
+
+Layer& Layer::operator=(Layer&& other) {
+ if (this != &other) {
+ Reset();
+ using std::swap;
+ swap(hardware_composer_layer_, other.hardware_composer_layer_);
+ swap(z_order_, other.z_order_);
+ swap(blending_, other.blending_);
+ swap(transform_, other.transform_);
+ swap(composition_type_, other.composition_type_);
+ swap(target_composition_type_, other.target_composition_type_);
+ swap(source_, other.source_);
+ swap(acquire_fence_, other.acquire_fence_);
+ swap(surface_rect_functions_applied_,
+ other.surface_rect_functions_applied_);
+ swap(pending_visibility_settings_, other.pending_visibility_settings_);
+ }
+ return *this;
}
void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
std::get<SourceBuffer>(source_) = {buffer};
}
-void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
-void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
+void Layer::SetBlending(HWC::BlendMode blending) {
+ if (blending_ != blending) {
+ blending_ = blending;
+ pending_visibility_settings_ = true;
+ }
+}
+
+void Layer::SetZOrder(size_t z_order) {
+ if (z_order_ != z_order) {
+ z_order_ = z_order;
+ pending_visibility_settings_ = true;
+ }
+}
IonBuffer* Layer::GetBuffer() {
struct Visitor {
return source_.Visit(Visitor{});
}
-void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) {
- if (!IsLayerSetup()) {
- ALOGE(
- "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
- "unused Layer!");
- return;
+void Layer::UpdateVisibilitySettings() {
+ if (pending_visibility_settings_) {
+ pending_visibility_settings_ = false;
+
+ HWC::Error error;
+ hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+
+ error = composer_->setLayerBlendMode(
+ display, hardware_composer_layer_,
+ blending_.cast<Hwc2::IComposerClient::BlendMode>());
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
+ error.to_string().c_str());
+
+ error =
+ composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting z_ order: %s",
+ error.to_string().c_str());
}
+}
+void Layer::UpdateLayerSettings() {
HWC::Error error;
hwc2_display_t display = HWC_DISPLAY_PRIMARY;
- error = hidl_->setLayerCompositionType(
+ UpdateVisibilitySettings();
+
+ error = composer_->setLayerCompositionType(
display, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
ALOGE_IF(
"Layer::UpdateLayerSettings: Error setting layer composition type: %s",
error.to_string().c_str());
- error = hidl_->setLayerBlendMode(
- display, hardware_composer_layer_,
- blending_.cast<Hwc2::IComposerClient::BlendMode>());
- ALOGE_IF(error != HWC::Error::None,
- "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
- error.to_string().c_str());
-
// TODO(eieio): Use surface attributes or some other mechanism to control
// the layer display frame.
- error = hidl_->setLayerDisplayFrame(
+ error = composer_->setLayerDisplayFrame(
display, hardware_composer_layer_,
- {0, 0, display_metrics.width, display_metrics.height});
+ {0, 0, display_metrics_.width, display_metrics_.height});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer display frame: %s",
error.to_string().c_str());
- error = hidl_->setLayerVisibleRegion(
+ error = composer_->setLayerVisibleRegion(
display, hardware_composer_layer_,
- {{0, 0, display_metrics.width, display_metrics.height}});
+ {{0, 0, display_metrics_.width, display_metrics_.height}});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer visible region: %s",
error.to_string().c_str());
- error = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+ error =
+ composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
error.to_string().c_str());
-
- error = hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
- ALOGE_IF(error != HWC::Error::None,
- "Layer::UpdateLayerSettings: Error setting z_ order: %s",
- error.to_string().c_str());
}
-void Layer::CommonLayerSetup(const HWCDisplayMetrics& display_metrics) {
+void Layer::CommonLayerSetup() {
HWC::Error error =
- hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
- ALOGE_IF(
- error != HWC::Error::None,
- "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
- error.to_string().c_str());
- UpdateLayerSettings(display_metrics);
+ composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::CommonLayerSetup: Failed to create layer on primary "
+ "display: %s",
+ error.to_string().c_str());
+ UpdateLayerSettings();
}
void Layer::Prepare() {
std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
});
- // When a layer is first setup there may be some time before the first buffer
- // arrives. Setup the HWC layer as a solid color to stall for time until the
- // first buffer arrives. Once the first buffer arrives there will always be a
- // buffer for the frame even if it is old.
+ // Update any visibility (blending, z-order) changes that occurred since
+ // last prepare.
+ UpdateVisibilitySettings();
+
+ // When a layer is first setup there may be some time before the first
+ // buffer arrives. Setup the HWC layer as a solid color to stall for time
+ // until the first buffer arrives. Once the first buffer arrives there will
+ // always be a buffer for the frame even if it is old.
if (!handle.get()) {
if (composition_type_ == HWC::Composition::Invalid) {
composition_type_ = HWC::Composition::SolidColor;
- hidl_->setLayerCompositionType(
+ composer_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
- hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- layer_color);
+ composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ layer_color);
} else {
// The composition type is already set. Nothing else to do until a
// buffer arrives.
} else {
if (composition_type_ != target_composition_type_) {
composition_type_ = target_composition_type_;
- hidl_->setLayerCompositionType(
+ composer_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
HWC::Error error{HWC::Error::None};
- error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_, 0, handle,
- acquire_fence_.Get());
+ error =
+ composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ 0, handle, acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer buffer: %s",
if (!surface_rect_functions_applied_) {
const float float_right = right;
const float float_bottom = bottom;
- error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_,
- {0, 0, float_right, float_bottom});
+ error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_,
+ {0, 0, float_right, float_bottom});
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer source crop: %s",
// source supplying buffers for the layer's contents.
class Layer {
public:
- Layer() {}
-
- // Releases any shared pointers and fence handles held by this instance.
- void Reset();
+ Layer() = default;
// Sets up the layer to use a display surface as its content source. The Layer
// automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
// |index| is the index of this surface in the DirectDisplaySurface array.
- void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
- const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_roder);
+ Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_roder);
// Sets up the layer to use a direct buffer as its content source. No special
// handling of the buffer is performed; responsibility for updating or
// |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- void Setup(const std::shared_ptr<IonBuffer>& buffer,
- const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order);
+ Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order);
+
+ Layer(Layer&&);
+ Layer& operator=(Layer&&);
+
+ ~Layer();
+
+ // Releases any shared pointers and fence handles held by this instance.
+ void Reset();
// Layers that use a direct IonBuffer should call this each frame to update
// which buffer will be used for the next PostLayers.
HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; }
bool IsLayerSetup() const { return !source_.empty(); }
- // Applies all of the settings to this layer using the hwc functions
- void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics);
-
int GetSurfaceId() const {
int surface_id = -1;
pdx::rpc::IfAnyOf<SourceSurface>::Call(
return buffer_id;
}
+ // Compares Layers by surface id.
+ bool operator<(const Layer& other) const {
+ return GetSurfaceId() < other.GetSurfaceId();
+ }
+ bool operator<(int surface_id) const {
+ return GetSurfaceId() < surface_id;
+ }
+
+ // Sets the composer instance used by all Layer instances.
+ static void SetComposer(Hwc2::Composer* composer) { composer_ = composer; }
+
+ // Sets the display metrics used by all Layer instances.
+ static void SetDisplayMetrics(HWCDisplayMetrics display_metrics) {
+ display_metrics_ = display_metrics;
+ }
+
private:
- void CommonLayerSetup(const HWCDisplayMetrics& display_metrics);
+ void CommonLayerSetup();
+
+ // Applies all of the settings to this layer using the hwc functions
+ void UpdateLayerSettings();
- Hwc2::Composer* hidl_ = nullptr;
+ // Applies visibility settings that may have changed.
+ void UpdateVisibilitySettings();
+
+ // Composer instance shared by all instances of Layer. This must be set
+ // whenever a new instance of the Composer is created. This may be set to
+ // nullptr as long as there are no instances of Layer that might need to use
+ // it.
+ static Hwc2::Composer* composer_;
+
+ // Display metrics shared by all instances of Layer. This must be set at least
+ // once during VrFlinger initialization and is expected to remain constant
+ // thereafter.
+ static HWCDisplayMetrics display_metrics_;
// The hardware composer layer and metrics to use during the prepare cycle.
hwc2_layer_t hardware_composer_layer_ = 0;
pdx::LocalHandle acquire_fence_;
bool surface_rect_functions_applied_ = false;
+ bool pending_visibility_settings_ = true;
Layer(const Layer&) = delete;
void operator=(const Layer&) = delete;
using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
using RequestDisplayCallback = std::function<void(bool)>;
- // Since there is no universal way to query the number of hardware layers,
- // just set it to 4 for now.
- static constexpr size_t kMaxHardwareLayers = 4;
-
HardwareComposer();
~HardwareComposer();
- bool Initialize(Hwc2::Composer* hidl,
+ bool Initialize(Hwc2::Composer* composer,
RequestDisplayCallback request_display_callback);
bool IsInitialized() const { return initialized_; }
void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
private:
- HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display,
- hwc2_config_t config,
+ HWC::Error GetDisplayAttribute(Hwc2::Composer* composer,
+ hwc2_display_t display, hwc2_config_t config,
hwc2_attribute_t attributes,
int32_t* out_value) const;
- HWC::Error GetDisplayMetrics(Hwc2::Composer* hidl, hwc2_display_t display,
+ HWC::Error GetDisplayMetrics(Hwc2::Composer* composer, hwc2_display_t display,
hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const;
int64_t timestamp) override;
const pdx::LocalHandle& GetVsyncEventFd() const;
int64_t GetVsyncTime();
+
private:
std::mutex vsync_mutex_;
pdx::LocalHandle vsync_event_fd_;
// the case of a timeout. If we're interrupted, kPostThreadInterrupted will be
// returned.
int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
- int requested_events,
- int timeout_ms);
+ int requested_events, int timeout_ms);
// WaitForVSync and SleepUntil are blocking calls made on the post thread that
// can be interrupted by a control thread. If interrupted, these calls return
bool initialized_;
- std::unique_ptr<Hwc2::Composer> hidl_;
- sp<ComposerCallback> hidl_callback_;
+ std::unique_ptr<Hwc2::Composer> composer_;
+ sp<ComposerCallback> composer_callback_;
RequestDisplayCallback request_display_callback_;
// Display metrics of the physical display.
// thread and read by the post thread.
std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
- // The surfaces displayed by the post thread. Used exclusively by the post
- // thread.
- std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_;
-
- // Layer array for handling buffer flow into hardware composer layers.
- std::array<Layer, kMaxHardwareLayers> layers_;
- size_t active_layer_count_ = 0;
+ // Layer set for handling buffer flow into hardware composer layers. This
+ // vector must be sorted by surface_id in ascending order.
+ std::vector<Layer> layers_;
// Handler to hook vsync events outside of this class.
VSyncCallback vsync_callback_;
std::thread post_thread_;
// Post thread state machine and synchronization primitives.
- PostThreadStateType post_thread_state_{
- PostThreadState::Idle | PostThreadState::Suspended};
+ PostThreadStateType post_thread_state_{PostThreadState::Idle |
+ PostThreadState::Suspended};
std::atomic<bool> post_thread_quiescent_{true};
bool post_thread_resumed_{false};
pdx::LocalHandle post_thread_event_fd_;