summaryrefslogtreecommitdiff
path: root/hwc2/hwc2_display.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'hwc2/hwc2_display.cpp')
-rw-r--r--hwc2/hwc2_display.cpp191
1 files changed, 181 insertions, 10 deletions
diff --git a/hwc2/hwc2_display.cpp b/hwc2/hwc2_display.cpp
index a874aba..fa8f0e9 100644
--- a/hwc2/hwc2_display.cpp
+++ b/hwc2/hwc2_display.cpp
@@ -17,6 +17,7 @@
#include <cutils/log.h>
#include <inttypes.h>
+#include <map>
#include <vector>
#include <array>
@@ -31,9 +32,12 @@ hwc2_display::hwc2_display(hwc2_display_t id, int adf_intf_fd,
name(),
connection(connection),
type(type),
+ display_state(modified),
+ client_target_used(false),
windows(),
layers(),
vsync_enabled(HWC2_VSYNC_DISABLE),
+ changed_comp_types(),
configs(),
active_config(0),
power_mode(power_mode),
@@ -57,6 +61,7 @@ hwc2_error_t hwc2_display::set_connection(hwc2_connection_t connection)
return HWC2_ERROR_BAD_PARAMETER;
}
+ display_state = modified;
this->connection = connection;
return HWC2_ERROR_NONE;
}
@@ -128,6 +133,119 @@ hwc2_error_t hwc2_display::set_vsync_enabled(hwc2_vsync_t enabled)
return HWC2_ERROR_NONE;
}
+hwc2_error_t hwc2_display::validate_display(uint32_t *out_num_types,
+ uint32_t *out_num_requests)
+{
+ if (display_state == valid) {
+ *out_num_types = 0;
+ *out_num_requests = 0;
+ return HWC2_ERROR_NONE;
+ }
+
+ clear_windows();
+ changed_comp_types.clear();
+
+ assign_composition();
+
+ *out_num_requests = 0;
+ *out_num_types = changed_comp_types.size();
+
+ for (auto &lyr: layers)
+ lyr.second.set_modified(false);
+
+ if (*out_num_types > 0) {
+ display_state = invalid;
+ return HWC2_ERROR_HAS_CHANGES;
+ }
+
+ display_state = valid;
+ return HWC2_ERROR_NONE;
+}
+
+void hwc2_display::assign_composition()
+{
+ hwc2_error_t ret;
+
+ std::map<uint32_t, hwc2_layer_t> ordered_layers;
+ for (auto &lyr: layers)
+ ordered_layers.emplace(lyr.second.get_z_order(), lyr.second.get_id());
+
+ bool client_target_assigned = false;
+
+ /* If there will definitely be a client target, assign it to the front most
+ * window */
+ if (layers.size() > windows.size()) {
+ ret = assign_client_target_window(0);
+ ALOG_ASSERT(ret == HWC2_ERROR_NONE, "No valid client target window");
+
+ client_target_assigned = true;
+ }
+
+ bool retry_assignment;
+
+ do {
+ retry_assignment = false;
+ /* The display controller uses a different z order than SurfaceFlinger */
+ uint32_t z_order = windows.size() - 1;
+ client_target_used = false;
+
+ /* Iterate over the layers from the back to the front.
+ * assign windows to device layers. Upon reaching a layer that must
+ * be composed by the client all subsequent layers will be assigned
+ * client composition */
+ for (auto &ordered_layer: ordered_layers) {
+ hwc2_layer_t lyr_id = ordered_layer.second;
+ hwc2_composition_t comp_type = layers.find(
+ lyr_id)->second.get_comp_type();
+
+ if (comp_type == HWC2_COMPOSITION_INVALID) {
+ ALOGW("dpy %" PRIu64 " lyr %" PRIu64 ": invalid composition"
+ " type %u", id, lyr_id, comp_type);
+ continue;
+ }
+
+ /* If the layer is not overlapped and can be assigned a window,
+ assign it and continue to the next layer */
+ if (comp_type == HWC2_COMPOSITION_DEVICE && !client_target_used
+ && assign_layer_window(z_order, lyr_id) == HWC2_ERROR_NONE) {
+ z_order--;
+ continue;
+ }
+
+ /* The layer will be composited into a client target buffer so
+ * find a window for the client target */
+ if (!client_target_assigned) {
+
+ ret = assign_client_target_window(0);
+ if (ret != HWC2_ERROR_NONE) {
+ /* If no client target can be assigned, clear all the
+ * windows, assign a client target and retry assigning
+ * windows */
+ retry_assignment = true;
+
+ changed_comp_types.clear();
+ clear_windows();
+
+ ret = assign_client_target_window(0);
+ ALOG_ASSERT(ret == HWC2_ERROR_NONE, "No valid client target"
+ " window");
+
+ client_target_assigned = true;
+ break;
+ }
+
+ client_target_assigned = true;
+ }
+
+ /* Assign the layer to client composition */
+ if (comp_type != HWC2_COMPOSITION_CLIENT)
+ changed_comp_types.emplace(lyr_id, HWC2_COMPOSITION_CLIENT);
+
+ client_target_used = true;
+ }
+ } while (retry_assignment);
+}
+
void hwc2_display::init_windows()
{
for (auto it = windows.begin(); it != windows.end(); it++)
@@ -282,6 +400,8 @@ hwc2_error_t hwc2_display::set_active_config(
hwc2_error_t hwc2_display::create_layer(hwc2_layer_t *out_layer)
{
+ display_state = modified;
+
hwc2_layer_t lyr_id = hwc2_layer::get_next_id();
layers.emplace(std::piecewise_construct, std::forward_as_tuple(lyr_id),
std::forward_as_tuple(lyr_id));
@@ -298,6 +418,7 @@ hwc2_error_t hwc2_display::destroy_layer(hwc2_layer_t lyr_id)
return HWC2_ERROR_BAD_LAYER;
}
+ display_state = modified;
layers.erase(lyr_id);
return HWC2_ERROR_NONE;
}
@@ -311,7 +432,12 @@ hwc2_error_t hwc2_display::set_layer_composition_type(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_comp_type(comp_type);
+ hwc2_error_t ret = it->second.set_comp_type(comp_type);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_buffer(hwc2_layer_t lyr_id,
@@ -323,7 +449,12 @@ hwc2_error_t hwc2_display::set_layer_buffer(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_buffer(handle, acquire_fence);
+ hwc2_error_t ret = it->second.set_buffer(handle, acquire_fence);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_dataspace(hwc2_layer_t lyr_id,
@@ -335,7 +466,12 @@ hwc2_error_t hwc2_display::set_layer_dataspace(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_dataspace(dataspace);
+ hwc2_error_t ret = it->second.set_dataspace(dataspace);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_display_frame(hwc2_layer_t lyr_id,
@@ -347,7 +483,12 @@ hwc2_error_t hwc2_display::set_layer_display_frame(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_display_frame(display_frame);
+ hwc2_error_t ret = it->second.set_display_frame(display_frame);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_source_crop(hwc2_layer_t lyr_id,
@@ -359,7 +500,12 @@ hwc2_error_t hwc2_display::set_layer_source_crop(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_source_crop(source_crop);
+ hwc2_error_t ret = it->second.set_source_crop(source_crop);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_z_order(hwc2_layer_t lyr_id, uint32_t z_order)
@@ -370,7 +516,12 @@ hwc2_error_t hwc2_display::set_layer_z_order(hwc2_layer_t lyr_id, uint32_t z_ord
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_z_order(z_order);
+ hwc2_error_t ret = it->second.set_z_order(z_order);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_surface_damage(hwc2_layer_t lyr_id,
@@ -394,7 +545,12 @@ hwc2_error_t hwc2_display::set_layer_blend_mode(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_blend_mode(blend_mode);
+ hwc2_error_t ret = it->second.set_blend_mode(blend_mode);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_plane_alpha(hwc2_layer_t lyr_id, float plane_alpha)
@@ -405,7 +561,12 @@ hwc2_error_t hwc2_display::set_layer_plane_alpha(hwc2_layer_t lyr_id, float plan
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_plane_alpha(plane_alpha);
+ hwc2_error_t ret = it->second.set_plane_alpha(plane_alpha);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_transform(hwc2_layer_t lyr_id,
@@ -417,7 +578,12 @@ hwc2_error_t hwc2_display::set_layer_transform(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_transform(transform);
+ hwc2_error_t ret = it->second.set_transform(transform);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_visible_region(hwc2_layer_t lyr_id,
@@ -429,7 +595,12 @@ hwc2_error_t hwc2_display::set_layer_visible_region(hwc2_layer_t lyr_id,
return HWC2_ERROR_BAD_LAYER;
}
- return it->second.set_visible_region(visible_region);
+ hwc2_error_t ret = it->second.set_visible_region(visible_region);
+
+ if (it->second.get_modified())
+ display_state = modified;
+
+ return ret;
}
hwc2_error_t hwc2_display::set_layer_color(hwc2_layer_t lyr_id,