OSDN Git Service

drm_hwcomposer: always put protected layers on hardware planes
authorZach Reizner <zachr@google.com>
Tue, 27 Oct 2015 23:18:06 +0000 (16:18 -0700)
committerZach Reizner <zachr@google.com>
Sat, 7 Nov 2015 01:41:28 +0000 (17:41 -0800)
Protected layers will not work inside of the GLWorker, so we are forced to put
them into planes directly.

Because we can now receive display contents which can never be properly
composited (e.g. 4 protected layers on hardware with only 3 planes), some
compromises had to be made for the composition planning algorithm. First all
protected layers are given a plane. Then the remaining planes are used by the
remaining layers, pre-composite buffer, and squash buffer. In the case where
there are too few planes for both a pre-composite buffer and squash buffer,
everything gets pushed into the pre-composite buffer and the squash buffer
will not be composited onto the screen. Another major limitation is that any
unprotected layers appearing behind a protected layer will actually appear on
top of that protected layer.

BUG=chrome-os-partner:43674
TEST=run protected content with lots of other layers

Change-Id: I94620d93f68ca14dc1966422dc89035ab84e3ff4

drmdisplaycomposition.cpp
drmdisplaycomposition.h
drmdisplaycompositor.cpp
drmhwcomposer.h
hwcomposer.cpp

index e712b64..9e591ea 100644 (file)
@@ -154,6 +154,20 @@ static DrmPlane *TakePlane(DrmCrtc *crtc,
   return TakePlane(crtc, overlay_planes);
 }
 
+void DrmDisplayComposition::EmplaceCompositionPlane(
+    size_t source_layer, std::vector<DrmPlane *> *primary_planes,
+    std::vector<DrmPlane *> *overlay_planes) {
+  DrmPlane *plane = TakePlane(crtc_, primary_planes, overlay_planes);
+  if (plane == NULL) {
+    ALOGE(
+        "Failed to add composition plane because there are no planes "
+        "remaining");
+    return;
+  }
+  composition_planes_.emplace_back(
+      DrmCompositionPlane{plane, crtc_, source_layer});
+}
+
 static std::vector<size_t> SetBitsToVector(uint64_t in, size_t *index_map) {
   std::vector<size_t> out;
   size_t msb = sizeof(in) * 8 - 1;
@@ -324,49 +338,64 @@ int DrmDisplayComposition::Plan(SquashState *squash,
     }
   }
 
+  // All protected layers get first usage of planes
   std::vector<size_t> layers_remaining;
   for (size_t layer_index = 0; layer_index < layers_.size(); layer_index++) {
-    // Skip layers that were completely squashed
-    if (layer_squash_area[layer_index] >=
-        layers_[layer_index].display_frame.area()) {
+    if (!layers_[layer_index].protected_usage() || planes_can_use == 0) {
+      layers_remaining.push_back(layer_index);
       continue;
     }
+    EmplaceCompositionPlane(layer_index, primary_planes, overlay_planes);
+    planes_can_use--;
+  }
 
-    layers_remaining.push_back(layer_index);
+  if (planes_can_use == 0 && layers_remaining.size() > 0) {
+    ALOGE("Protected layers consumed all hardware planes");
+    return CreateAndAssignReleaseFences();
   }
 
-  if (use_squash_framebuffer)
-    planes_can_use--;
+  std::vector<size_t> layers_remaining_if_squash;
+  for (size_t layer_index : layers_remaining) {
+    if (layer_squash_area[layer_index] <
+        layers_[layer_index].display_frame.area())
+      layers_remaining_if_squash.push_back(layer_index);
+  }
+
+  if (use_squash_framebuffer) {
+    if (planes_can_use > 1 || layers_remaining_if_squash.size() == 0) {
+      layers_remaining = std::move(layers_remaining_if_squash);
+      planes_can_use--;  // Reserve plane for squashing
+    } else {
+      use_squash_framebuffer = false;  // The squash buffer is still rendered
+    }
+  }
 
   if (layers_remaining.size() > planes_can_use)
-    planes_can_use--;
+    planes_can_use--;  // Reserve one for pre-compositing
 
+  // Whatever planes that are not reserved get assigned a layer
   size_t last_composition_layer = 0;
   for (last_composition_layer = 0;
        last_composition_layer < layers_remaining.size() && planes_can_use > 0;
        last_composition_layer++, planes_can_use--) {
-    composition_planes_.emplace_back(
-        DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
-                            crtc_, layers_remaining[last_composition_layer]});
+    EmplaceCompositionPlane(layers_remaining[last_composition_layer],
+                            primary_planes, overlay_planes);
   }
 
   layers_remaining.erase(layers_remaining.begin(),
                          layers_remaining.begin() + last_composition_layer);
 
   if (layers_remaining.size() > 0) {
-    composition_planes_.emplace_back(
-        DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
-                            crtc_, DrmCompositionPlane::kSourcePreComp});
-
+    EmplaceCompositionPlane(DrmCompositionPlane::kSourcePreComp, primary_planes,
+                            overlay_planes);
     SeparateLayers(layers_.data(), layers_remaining.data(),
                    layers_remaining.size(), exclude_rects.data(),
                    exclude_rects.size(), pre_comp_regions_);
   }
 
   if (use_squash_framebuffer) {
-    composition_planes_.emplace_back(
-        DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
-                            crtc_, DrmCompositionPlane::kSourceSquash});
+    EmplaceCompositionPlane(DrmCompositionPlane::kSourceSquash, primary_planes,
+                            overlay_planes);
   }
 
   return CreateAndAssignReleaseFences();
@@ -485,6 +514,9 @@ void DrmDisplayComposition::Dump(std::ostringstream *out) const {
 
     DumpBuffer(layer.buffer, out);
 
+    if (layer.protected_usage())
+      *out << " protected";
+
     *out << " transform=" << TransformToString(layer.transform)
          << " blending[a=" << (int)layer.alpha
          << "]=" << BlendingToString(layer.blending) << " source_crop";
index e79466e..9be5fdd 100644 (file)
@@ -131,6 +131,9 @@ class DrmDisplayComposition {
 
   int IncreaseTimelineToPoint(int point);
 
+  void EmplaceCompositionPlane(size_t source_layer,
+                               std::vector<DrmPlane *> *primary_planes,
+                               std::vector<DrmPlane *> *overlay_planes);
   int CreateAndAssignReleaseFences();
 
   DrmResources *drm_ = NULL;
index e51d932..50a04d6 100644 (file)
@@ -74,9 +74,10 @@ void SquashState::GenerateHistory(DrmHwcLayer *layers, size_t num_layers,
   std::bitset<kMaxLayers> changed_layers;
   for (size_t i = 0; i < last_handles_.size(); i++) {
     DrmHwcLayer *layer = &layers[i];
-    if (last_handles_[i] != layer->sf_handle) {
+    // Protected layers can't be squashed so we treat them as constantly
+    // changing.
+    if (layer->protected_usage() || last_handles_[i] != layer->sf_handle)
       changed_layers.set(i);
-    }
   }
 
   for (size_t i = 0; i < regions_.size(); i++) {
index 2f36ad8..e0f8d2b 100644 (file)
@@ -155,6 +155,11 @@ struct DrmHwcLayer {
   buffer_handle_t get_usable_handle() const {
     return handle.get() != NULL ? handle.get() : sf_handle;
   }
+
+  bool protected_usage() const {
+    return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) ==
+           GRALLOC_USAGE_PROTECTED;
+  }
 };
 
 struct DrmHwcDisplayContents {
index f19407a..e755273 100644 (file)
@@ -302,13 +302,8 @@ int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
   ret = gralloc->perform(gralloc, GRALLOC_MODULE_PERFORM_GET_USAGE,
                          handle.get(), &gralloc_buffer_usage);
   if (ret) {
-    // TODO(zachr): Once GRALLOC_MODULE_PERFORM_GET_USAGE is implemented, remove
-    // "ret = 0" and enable the error logging code.
-    ret = 0;
-#if 0
     ALOGE("Failed to get usage for buffer %p (%d)", handle.get(), ret);
     return ret;
-#endif
   }
 
   return 0;