OSDN Git Service

Algorithm to detect disjoint regions for gpu composition.
authorarpallet <avinash.reddy.palleti@intel.com>
Sun, 29 Jan 2017 06:55:11 +0000 (22:55 -0800)
committerKalyan Kondapally <kalyan.kondapally@intel.com>
Tue, 31 Jan 2017 19:04:28 +0000 (11:04 -0800)
This algorithm traverse through x co-ordinates and at each
intersection of x co-ordinates, it will traverse through y
axis for intersections. At each y co-ordinate intersection
it will give out new layer with input layer ids active at
that point.

Jira: None.
Test: No graphics regressions on Linux and Android.

Signed-off-by: arpallet <avinash.reddy.palleti@intel.com>
Android.mk
Makefile.sources
common/compositor/compositor.cpp
common/utils/disjoint_layers.cpp [new file with mode: 0644]
common/utils/separate_rects.cpp [deleted file]
public/disjoint_layers.h [new file with mode: 0644]
public/hwcdefs.h
public/separate_rects.h [deleted file]

index c9e301d..87da9ec 100644 (file)
@@ -64,7 +64,7 @@ LOCAL_SRC_FILES := \
        common/display/pageflipeventhandler.cpp \
        common/utils/drmscopedtypes.cpp \
        common/utils/hwcthread.cpp \
-       common/utils/separate_rects.cpp \
+       common/utils/disjoint_layers.cpp \
        os/android/grallocbufferhandler.cpp \
        os/android/drmhwctwo.cpp
 
index e00eb8e..c880ee5 100644 (file)
@@ -17,7 +17,7 @@ common_SOURCES =              \
     common/display/pageflipeventhandler.cpp \
     common/utils/drmscopedtypes.cpp \
     common/utils/hwcthread.cpp \
-    common/utils/separate_rects.cpp \
+    common/utils/disjoint_layers.cpp \
     os/linux/gbmbufferhandler.cpp \
        $(NULL)
 
index 0e84ecc..cdbcce7 100644 (file)
 
 #include <xf86drmMode.h>
 
+#include "disjoint_layers.h"
 #include "displayplanestate.h"
 #include "hwctrace.h"
 #include "nativegpuresource.h"
 #include "nativesurface.h"
 #include "nativesync.h"
-#include "renderstate.h"
-#include "renderer.h"
 #include "overlaylayer.h"
-#include "separate_rects.h"
+#include "renderer.h"
+#include "renderstate.h"
 #include "scopedrendererstate.h"
 
 namespace hwcomposer {
@@ -285,13 +285,13 @@ void Compositor::SeparateLayers(const std::vector<size_t> &dedicated_layers,
     return display_frame[layer_index];
   });
 
-  std::vector<separate_rects::RectSet<uint64_t, int>> separate_regions;
-  separate_rects::separate_rects_64(layer_rects, &separate_regions);
+  std::vector<RectSet<int>> separate_regions;
+  get_draw_regions(layer_rects, &separate_regions);
   uint64_t exclude_mask = ((uint64_t)1 << num_exclude_rects) - 1;
   uint64_t dedicated_mask = (((uint64_t)1 << dedicated_layers.size()) - 1)
                             << num_exclude_rects;
 
-  for (separate_rects::RectSet<uint64_t, int> &region : separate_regions) {
+  for (RectSet<int> &region : separate_regions) {
     if (region.id_set.getBits() & exclude_mask)
       continue;
 
diff --git a/common/utils/disjoint_layers.cpp b/common/utils/disjoint_layers.cpp
new file mode 100644 (file)
index 0000000..20745d8
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+// Copyright (c) 2016 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "disjoint_layers.h"
+#include <assert.h>
+#include <stdint.h>
+#include <algorithm>
+#include <iostream>
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+#include <vector>
+#include "hwctrace.h"
+
+namespace hwcomposer {
+
+enum EventType { START, END };
+
+struct YPOI {
+  EventType type;
+  uint64_t y;
+  uint64_t rect_id;
+
+  bool operator<(const YPOI &rhs) const {
+    if (y == rhs.y)
+      return rect_id < rhs.rect_id;
+    else
+      return (y < rhs.y);
+  }
+};
+
+// Any region will have start X and set of Y coordinates.
+struct Region {
+  uint64_t sx;
+  std::set<YPOI> y_points;
+  RectIDs rect_ids;
+};
+
+// POI is the point of interest while traversing through x coordinates
+struct POI {
+  EventType type;
+  uint64_t rect_id;
+  uint64_t x;
+  uint64_t top_y;
+  uint64_t bot_y;
+
+  bool operator<(const POI &rhs) const {
+    return (x <= rhs.x);
+  }
+};
+
+// This function will take active region and right x
+// For an active region there will be set of YPOI
+// It will traverse through each y_poi and given out
+// rectangle with rect_ids active at that time.
+void GenerateOutLayers(Region *reg, uint64_t x,
+                       std::vector<RectSet<int>> *out) {
+  Rect<int> out_rect;
+  out_rect.left = reg->sx;
+  out_rect.right = x;
+  RectIDs rect_ids;
+
+  for (std::set<YPOI>::iterator y_poi_it = reg->y_points.begin();
+       y_poi_it != reg->y_points.end(); y_poi_it++) {
+    const YPOI &y_poi = *y_poi_it;
+    // No need to check for start or end event
+    // as rect_ids is empty
+    if (rect_ids.isEmpty()) {
+      out_rect.top = y_poi.y;
+      rect_ids.add(y_poi.rect_id);
+    } else {
+      if(out_rect.top == (int)y_poi.y) {
+        if (y_poi.type == START) {
+          rect_ids.add(y_poi.rect_id);
+        } else {
+          rect_ids.subtract(y_poi.rect_id);
+        }
+        continue;
+      }
+      out_rect.bottom = y_poi.y;
+      out->emplace_back(RectSet<int>(rect_ids, out_rect));
+      out_rect.top = y_poi.y;
+      if (y_poi.type == START) {
+        rect_ids.add(y_poi.rect_id);
+      } else {
+        rect_ids.subtract(y_poi.rect_id);
+      }
+    }
+  }
+}
+
+// This function will remove y coordinates corresponding to given rect_id
+void RemoveYpois(Region *reg, uint64_t rect_id) {
+  std::set<YPOI>::iterator top_it = reg->y_points.begin();
+  while (top_it != reg->y_points.end()) {
+    if ((*top_it).rect_id == rect_id) {
+      reg->y_points.erase(top_it++);
+    } else {
+      top_it++;
+    }
+  }
+}
+
+bool compare_region(const Region *first, const Region *second) {
+  uint64_t first_min_y = (*(first->y_points.begin())).y;
+  uint64_t second_min_y = (*(second->y_points.begin())).y;
+  return (first_min_y < second_min_y);
+}
+
+void get_draw_regions(const std::vector<Rect<int>> &in,
+                      std::vector<RectSet<int>> *out) {
+  if (in.size() > RectIDs::max_elements) {
+    return;
+  }
+
+  // Set of all point of interests from input rectangles.
+  std::set<POI> pois;
+  std::list<Region *> imp_reg;
+  std::list<Region> active_regions;
+
+  // This loop will add all point of interests into pois.
+  for (uint64_t i = 0; i < in.size(); i++) {
+    const Rect<int> &rect = in[i];
+
+    // Filter out empty or invalid rects.
+    if (rect.left >= rect.right || rect.top >= rect.bottom)
+      continue;
+
+    POI poi;
+    poi.rect_id = i;
+    poi.x = rect.left;
+    poi.top_y = rect.top;
+    poi.bot_y = rect.bottom;
+    poi.type = START;
+    pois.insert(poi);
+
+    poi.type = END;
+    poi.x = rect.right;
+    pois.insert(poi);
+  }
+
+  for (std::set<POI>::iterator it = pois.begin(); it != pois.end(); ++it) {
+    const POI &poi = *it;
+    // First rectangle has to be inserted into active region
+    // This condition will be true if existing all active
+    // regions are already copied to out.
+    // If current poi is of type END there are no active regions,
+    // then this poi might already covered in previous pass
+    if (active_regions.size() == 0 && poi.type == START) {
+      Region reg;
+      reg.sx = poi.x;
+      YPOI y_poi;
+
+      y_poi.rect_id = poi.rect_id;
+      y_poi.type = START;
+      y_poi.y = poi.top_y;
+      reg.y_points.insert(y_poi);
+
+      y_poi.type = END;
+      y_poi.y = poi.bot_y;
+      reg.y_points.insert(y_poi);
+
+      RectIDs rectIds;
+      rectIds.add(poi.rect_id);
+      reg.rect_ids = rectIds;
+      active_regions.push_back(reg);
+      continue;
+    }
+
+    // If active_regions in not empty, Check if current
+    // poi y points fall in range of any existing
+    // active_regions.
+    // If yes, get that active region and do further processing
+    // If No, create a new region and insert into active regions
+    // If it is start event then there is possibility that multiple
+    // active_regions get impacted.
+    // If it is end event then one or none active_regions will get
+    // impacted.
+    bool found = false;
+    imp_reg.clear();
+    std::list<Region>::iterator it_reg = active_regions.begin();
+    while (it_reg != active_regions.end()) {
+      Region &cur_reg = *it_reg;
+      uint64_t min_y = (*(cur_reg.y_points.begin())).y;
+      uint64_t max_y = (*(cur_reg.y_points.rbegin())).y;
+      // If bottom y is less than minimum y in region or top y is greater than
+      // max y in region, then this region is not impacted by this rect
+      if (poi.bot_y <= min_y || poi.top_y >= max_y) {
+        it_reg++;
+        continue;
+      } else {
+        found = true;
+        // Found atleast one affected active region. If it is start event,
+        // add rect_id to cur_reg.rect_ids, also top_y and bot_y to
+        // cur_reg.y_points. if it is end event, remove rect_id from
+        // cur_reg.rect_ids and also top_y and bot_y from cur_reg.y_points.
+        // Also, if it is end event, check cur_reg.rect_ids is non empty,
+        // if it is empty remove region from active_regions.
+        // If it is end event, check next poi.x and see if it is same and
+        // those y coordinates fall in this region, if yes 1) remove
+        // that rect_id and y coordinates as well
+        // 2)contine to check next poi.x until you find mismatch x.
+        if (poi.x == cur_reg.sx) {
+          if (poi.type == START) {
+            cur_reg.rect_ids.add(poi.rect_id);
+            imp_reg.push_back(&cur_reg);
+         }
+
+         it_reg++;
+          continue;
+        }
+        if (poi.type == START) {
+          GenerateOutLayers(&cur_reg, poi.x, out);
+          cur_reg.sx = poi.x;
+          cur_reg.rect_ids.add(poi.rect_id);
+          imp_reg.push_back(&cur_reg);
+          it_reg++;
+        } else {
+          GenerateOutLayers(&cur_reg, poi.x, out);
+          RemoveYpois(&cur_reg, poi.rect_id);
+          cur_reg.sx = poi.x;
+          cur_reg.rect_ids.subtract(poi.rect_id);
+
+          std::set<POI>::iterator next_poi_it = it;
+          next_poi_it++;
+          for (; next_poi_it != pois.end(); next_poi_it++) {
+            const POI &next_poi = *next_poi_it;
+            if (next_poi.x != poi.x) {
+              break;
+            } else {
+              if (next_poi.bot_y <= min_y || next_poi.top_y >= max_y ||
+                  next_poi.type == START) {
+                continue;
+              }
+              cur_reg.rect_ids.subtract(next_poi.rect_id);
+              RemoveYpois(&cur_reg, next_poi.rect_id);
+            }
+          }
+          if (cur_reg.rect_ids.isEmpty()) {
+            active_regions.erase(it_reg++);
+          } else {
+            it_reg++;
+          }
+        }
+      }
+    }
+    // If no affected active region found, add new active region
+    if (!found && poi.type == START) {
+      Region reg;
+      reg.sx = poi.x;
+      YPOI y_poi;
+
+      y_poi.rect_id = poi.rect_id;
+      y_poi.type = START;
+      y_poi.y = poi.top_y;
+      reg.y_points.insert(y_poi);
+
+      y_poi.type = END;
+      y_poi.y = poi.bot_y;
+      reg.y_points.insert(y_poi);
+
+      RectIDs rectIds;
+      rectIds.add(poi.rect_id);
+      reg.rect_ids = rectIds;
+      active_regions.push_back(reg);
+    } else {
+      if (imp_reg.size() > 1 && poi.type == START) {
+        imp_reg.sort(compare_region);
+        uint64_t cur_y = 0;
+        for (std::list<Region *>::iterator cur_imp_reg_it = imp_reg.begin();
+             cur_imp_reg_it != imp_reg.end(); cur_imp_reg_it++) {
+          Region &cur_imp_reg = *(*cur_imp_reg_it);
+          YPOI y_poi;
+          y_poi.rect_id = poi.rect_id;
+          y_poi.type = START;
+
+          if (cur_y == 0) {
+            y_poi.y = poi.top_y;
+          } else {
+            y_poi.y = cur_y;
+          }
+          // This is to split vertical
+          // line into all impacted
+          // regions.
+          cur_imp_reg.y_points.insert(y_poi);
+          // Take bottom of current region as start of next impacted region
+          cur_y = (*(cur_imp_reg.y_points.rbegin())).y;
+          std::list<Region *>::iterator next_imp_reg_it = cur_imp_reg_it;
+          next_imp_reg_it++;
+          if (next_imp_reg_it == imp_reg.end()) {
+            // If there is an another
+            // region which is impacted, no
+            // need to add anything.
+            // if there is no other active region left,
+            // take bottom y and push into this active region
+            y_poi.y = poi.bot_y;
+          } else {
+            y_poi.y = cur_y;
+          }
+          y_poi.type = END;
+          cur_imp_reg.y_points.insert(y_poi);
+        }
+      } else if (imp_reg.size() == 1 && poi.type == START) {
+        // Only one region got impacted add y coordinated to that region
+        std::list<Region *>::iterator cur_imp_reg_it = imp_reg.begin();
+        YPOI y_poi;
+        y_poi.rect_id = poi.rect_id;
+        y_poi.type = START;
+        y_poi.y = poi.top_y;
+        (*cur_imp_reg_it)->y_points.insert(y_poi);
+        y_poi.type = END;
+        y_poi.y = poi.bot_y;
+        (*cur_imp_reg_it)->y_points.insert(y_poi);
+      }
+    }
+  }
+}
+
+}  // namespace hwcomposer
diff --git a/common/utils/separate_rects.cpp b/common/utils/separate_rects.cpp
deleted file mode 100644 (file)
index fc7ec26..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "separate_rects.h"
-#include <algorithm>
-#include <assert.h>
-#include <iostream>
-#include <map>
-#include <set>
-#include <utility>
-#include <vector>
-
-namespace separate_rects {
-
-enum EventType { START, END };
-
-template <typename TId, typename TNum>
-struct StartedRect {
-  IdSet<TId> id_set;
-  TNum left, top, bottom;
-
-  // Note that this->left is not part of the key. That field is only to mark the
-  // left edge of the rectangle.
-  bool operator<(const StartedRect<TId, TNum> &rhs) const {
-    return (top < rhs.top || (top == rhs.top && bottom < rhs.bottom)) ||
-           (top == rhs.top && bottom == rhs.bottom && id_set < rhs.id_set);
-  }
-};
-
-template <typename TId, typename TNum>
-struct SweepEvent {
-  EventType type;
-  union {
-    TNum x;
-    TNum y;
-  };
-
-  TId rect_id;
-
-  bool operator<(const SweepEvent<TId, TNum> &rhs) const {
-    return (y < rhs.y || (y == rhs.y && rect_id < rhs.rect_id));
-  }
-};
-
-template <typename TNum>
-std::ostream &operator<<(std::ostream &os, const Rect<TNum> &rect) {
-  return os << rect.bounds[0] << ", " << rect.bounds[1] << ", "
-            << rect.bounds[2] << ", " << rect.bounds[3];
-}
-
-template <typename TUInt>
-std::ostream &operator<<(std::ostream &os, const IdSet<TUInt> &obj) {
-  int bits = IdSet<TUInt>::max_elements;
-  TUInt mask = ((TUInt)0x1) << (bits - 1);
-  for (int i = 0; i < bits; i++)
-    os << ((obj.getBits() & (mask >> i)) ? "1" : "0");
-  return os;
-}
-
-template <typename TNum, typename TId>
-void separate_rects(const std::vector<Rect<TNum>> &in,
-                    std::vector<RectSet<TId, TNum>> *out) {
-  // Overview:
-  // This algorithm is a line sweep algorithm that travels from left to right.
-  // The sweep stops at each vertical edge of each input rectangle in sorted
-  // order of x-coordinate. At each stop, the sweep line is examined in order of
-  // y-coordinate from top to bottom. Along the way, a running set of rectangle
-  // IDs is either added to or subtracted from as the top and bottom edges are
-  // encountered, respectively. At each change of that running set, a copy of
-  // that set is recorded in along with the the y-coordinate it happened at in a
-  // list. This list is then interpreted as a sort of vertical cross section of
-  // our output set of non-overlapping rectangles. Based of the algorithm found
-  // at: http://stackoverflow.com/a/2755498
-
-  if (in.size() > IdSet<TId>::max_elements) {
-    return;
-  }
-
-  // Events are when the sweep line encounters the starting or ending edge of
-  // any input rectangle.
-  std::set<SweepEvent<TId, TNum>> sweep_h_events;  // Left or right bounds
-  std::set<SweepEvent<TId, TNum>> sweep_v_events;  // Top or bottom bounds
-
-  // A started rect is a rectangle whose left, top, bottom edge, and set of
-  // rectangle IDs is known. The key of this map includes all that information
-  // (except the left edge is never used to determine key equivalence or
-  // ordering),
-  std::map<StartedRect<TId, TNum>, bool> started_rects;
-
-  // This is cleared after every event. Its declaration is here to avoid
-  // reallocating a vector and its buffers every event.
-  std::vector<std::pair<TNum, IdSet<TId>>> active_regions;
-
-  // This pass will add rectangle start and end events to be triggered as the
-  // algorithm sweeps from left to right.
-  for (TId i = 0; i < in.size(); i++) {
-    const Rect<TNum> &rect = in[i];
-
-    // Filter out empty or invalid rects.
-    if (rect.left >= rect.right || rect.top >= rect.bottom)
-      continue;
-
-    SweepEvent<TId, TNum> evt;
-    evt.rect_id = i;
-
-    evt.type = START;
-    evt.x = rect.left;
-    sweep_h_events.insert(evt);
-
-    evt.type = END;
-    evt.x = rect.right;
-    sweep_h_events.insert(evt);
-  }
-
-  for (typename std::set<SweepEvent<TId, TNum>>::iterator it =
-           sweep_h_events.begin();
-       it != sweep_h_events.end(); ++it) {
-    const SweepEvent<TId, TNum> &h_evt = *it;
-    const Rect<TNum> &rect = in[h_evt.rect_id];
-
-    // During this event, we have encountered a vertical starting or ending edge
-    // of a rectangle so want to append or remove (respectively) that rectangles
-    // top and bottom from the vertical sweep line.
-    SweepEvent<TId, TNum> v_evt;
-    v_evt.rect_id = h_evt.rect_id;
-    if (h_evt.type == START) {
-      v_evt.type = START;
-      v_evt.y = rect.top;
-      sweep_v_events.insert(v_evt);
-
-      v_evt.type = END;
-      v_evt.y = rect.bottom;
-      sweep_v_events.insert(v_evt);
-    } else {
-      v_evt.type = START;
-      v_evt.y = rect.top;
-      typename std::set<SweepEvent<TId, TNum>>::iterator start_it =
-          sweep_v_events.find(v_evt);
-      assert(start_it != sweep_v_events.end());
-      sweep_v_events.erase(start_it);
-
-      v_evt.type = END;
-      v_evt.y = rect.bottom;
-      typename std::set<SweepEvent<TId, TNum>>::iterator end_it =
-          sweep_v_events.find(v_evt);
-      assert(end_it != sweep_v_events.end());
-      sweep_v_events.erase(end_it);
-    }
-
-    // Peeks ahead to see if there are other rectangles sharing a vertical edge
-    // with the current sweep line. If so, we want to continue marking up the
-    // sweep line before actually processing the rectangles the sweep line is
-    // intersecting.
-    typename std::set<SweepEvent<TId, TNum>>::iterator next_it = it;
-    ++next_it;
-    if (next_it != sweep_h_events.end()) {
-      if (next_it->x == h_evt.x) {
-        continue;
-      }
-    }
-
-#ifdef RECTS_DEBUG
-    std::cout << h_evt.x << std::endl;
-#endif
-
-    // After the following for loop, active_regions will be a list of
-    // y-coordinates paired with the set of rectangle IDs that are intersect at
-    // that y-coordinate (and the current sweep line's x-coordinate). For
-    // example if the current sweep line were the left edge of a scene with only
-    // one rectangle of ID 0 and bounds (left, top, right, bottom) == (2, 3, 4,
-    // 5), active_regions will be [({ 0 }, 3), {}, 5].
-    active_regions.clear();
-    IdSet<TId> active_set;
-    for (typename std::set<SweepEvent<TId, TNum>>::iterator it =
-             sweep_v_events.begin();
-         it != sweep_v_events.end(); ++it) {
-      const SweepEvent<TId, TNum> &v_evt = *it;
-
-      if (v_evt.type == START) {
-        active_set.add(v_evt.rect_id);
-      } else {
-        active_set.subtract(v_evt.rect_id);
-      }
-
-      if (active_regions.size() > 0 && active_regions.back().first == v_evt.y) {
-        active_regions.back().second = active_set;
-      } else {
-        active_regions.emplace_back(std::make_pair(v_evt.y, active_set));
-      }
-    }
-
-#ifdef RECTS_DEBUG
-    std::cout << "x:" << h_evt.x;
-    for (std::vector<std::pair<TNum, IdSet>>::iterator it =
-             active_regions.begin();
-         it != active_regions.end(); ++it) {
-      std::cout << " " << it->first << "(" << it->second << ")"
-                << ",";
-    }
-    std::cout << std::endl;
-#endif
-
-    // To determine which started rectangles are ending this event, we make them
-    // all as false, or unseen during this sweep line.
-    for (typename std::map<StartedRect<TId, TNum>, bool>::iterator it =
-             started_rects.begin();
-         it != started_rects.end(); ++it) {
-      it->second = false;
-    }
-
-    // This for loop will iterate all potential new rectangles and either
-    // discover it was already started (and then mark it true), or that it is a
-    // new rectangle and add it to the started rectangles. A started rectangle
-    // is unique if it has a distinct top, bottom, and set of rectangle IDs.
-    // This is tricky because a potential rectangle could be encountered here
-    // that has a non-unique top and bottom, so it shares geometry with an
-    // already started rectangle, but the set of rectangle IDs differs. In that
-    // case, we have a new rectangle, and the already existing started rectangle
-    // will not be marked as seen ("true" in the std::pair) and will get ended
-    // by the for loop after this one. This is as intended.
-    for (typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator it =
-             active_regions.begin();
-         it != active_regions.end(); ++it) {
-      IdSet<TId> region_set = it->second;
-
-      if (region_set.isEmpty())
-        continue;
-
-      // An important property of active_regions is that each region where a set
-      // of rectangles applies is bounded at the bottom by the next (in the
-      // vector) region's starting y-coordinate.
-      typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator next_it = it;
-      ++next_it;
-      assert(next_it != active_regions.end());
-
-      TNum region_top = it->first;
-      TNum region_bottom = next_it->first;
-
-      StartedRect<TId, TNum> rect_key;
-      rect_key.id_set = region_set;
-      rect_key.left = h_evt.x;
-      rect_key.top = region_top;
-      rect_key.bottom = region_bottom;
-
-      // Remember that rect_key.left is ignored for the purposes of searching
-      // the started rects. This follows from the fact that a previously started
-      // rectangle would by definition have a left bound less than the current
-      // event's x-coordinate. We are interested in continuing the started
-      // rectangles by marking them seen (true) but we don't know, care, or wish
-      // to change the left bound at this point. If there are no matching
-      // rectangles for this region, start a new one and mark it as seen (true).
-      typename std::map<StartedRect<TId, TNum>, bool>::iterator
-          started_rect_it = started_rects.find(rect_key);
-      if (started_rect_it == started_rects.end()) {
-        started_rects[rect_key] = true;
-      } else {
-        started_rect_it->second = true;
-      }
-    }
-
-    // This for loop ends all rectangles that were unseen during this event.
-    // Because this is the first event where we didn't see this rectangle, it's
-    // right edge is exactly the current event's x-coordinate. With this, we
-    // have the final piece of information to output this rectangle's geometry
-    // and set of input rectangle IDs. To end a started rectangle, we erase it
-    // from the started_rects map and append the completed rectangle to the
-    // output vector.
-    for (typename std::map<StartedRect<TId, TNum>, bool>::iterator it =
-             started_rects.begin();
-         it != started_rects.end();
-         /* inc in body */) {
-      if (!it->second) {
-        const StartedRect<TId, TNum> &proto_rect = it->first;
-        Rect<TNum> out_rect;
-        out_rect.left = proto_rect.left;
-        out_rect.top = proto_rect.top;
-        out_rect.right = h_evt.x;
-        out_rect.bottom = proto_rect.bottom;
-        out->emplace_back(RectSet<TId, TNum>(proto_rect.id_set, out_rect));
-        started_rects.erase(it++);  // Also increments out iterator.
-
-#ifdef RECTS_DEBUG
-        std::cout << "    <" << proto_rect.id_set << "(" << rect << ")"
-                  << std::endl;
-#endif
-      } else {
-        // Remember this for loop has no built in increment step. We do it here.
-        ++it;
-      }
-    }
-  }
-}
-
-void separate_frects_64(const std::vector<Rect<float>> &in,
-                        std::vector<RectSet<uint64_t, float>> *out) {
-  separate_rects(in, out);
-}
-
-void separate_rects_64(const std::vector<Rect<int>> &in,
-                       std::vector<RectSet<uint64_t, int>> *out) {
-  separate_rects(in, out);
-}
-
-}  // namespace separate_rects
-
-#ifdef RECTS_TEST
-
-using namespace separate_rects;
-
-int main(int argc, char **argv) {
-#define RectSet RectSet<TId, TNum>
-#define Rect Rect<TNum>
-#define IdSet IdSet<TId>
-  typedef uint64_t TId;
-  typedef float TNum;
-
-  std::vector<Rect> in;
-  std::vector<RectSet> out;
-  std::vector<RectSet> expected_out;
-
-  in.emplace_back({0, 0, 4, 5});
-  in.emplace_back({2, 0, 6, 6});
-  in.emplace_back({4, 0, 8, 5});
-  in.emplace_back({0, 7, 8, 9});
-
-  in.emplace_back({10, 0, 18, 5});
-  in.emplace_back({12, 0, 16, 5});
-
-  in.emplace_back({20, 11, 24, 17});
-  in.emplace_back({22, 13, 26, 21});
-  in.emplace_back({32, 33, 36, 37});
-  in.emplace_back({30, 31, 38, 39});
-
-  in.emplace_back({40, 43, 48, 45});
-  in.emplace_back({44, 41, 46, 47});
-
-  in.emplace_back({50, 51, 52, 53});
-  in.emplace_back({50, 51, 52, 53});
-  in.emplace_back({50, 51, 52, 53});
-
-  in.emplace_back({0, 0, 0, 10});
-  in.emplace_back({0, 0, 10, 0});
-  in.emplace_back({10, 0, 0, 10});
-  in.emplace_back({0, 10, 10, 0});
-
-  for (int i = 0; i < 100000; i++) {
-    out.clear();
-    separate_rects(in, &out);
-  }
-
-  for (int i = 0; i < out.size(); i++) {
-    std::cout << out[i].id_set << "(" << out[i].rect << ")" << std::endl;
-  }
-
-  std::cout << "# of rects: " << out.size() << std::endl;
-
-  expected_out.emplace_back(RectSet(IdSet(0), Rect(0, 0, 2, 5)));
-  expected_out.emplace_back(RectSet(IdSet(1), Rect(2, 5, 6, 6)));
-  expected_out.emplace_back(RectSet(IdSet(1) | 0, Rect(2, 0, 4, 5)));
-  expected_out.emplace_back(RectSet(IdSet(1) | 2, Rect(4, 0, 6, 5)));
-  expected_out.emplace_back(RectSet(IdSet(2), Rect(6, 0, 8, 5)));
-  expected_out.emplace_back(RectSet(IdSet(3), Rect(0, 7, 8, 9)));
-  expected_out.emplace_back(RectSet(IdSet(4), Rect(10, 0, 12, 5)));
-  expected_out.emplace_back(RectSet(IdSet(5) | 4, Rect(12, 0, 16, 5)));
-  expected_out.emplace_back(RectSet(IdSet(4), Rect(16, 0, 18, 5)));
-  expected_out.emplace_back(RectSet(IdSet(6), Rect(20, 11, 22, 17)));
-  expected_out.emplace_back(RectSet(IdSet(6) | 7, Rect(22, 13, 24, 17)));
-  expected_out.emplace_back(RectSet(IdSet(6), Rect(22, 11, 24, 13)));
-  expected_out.emplace_back(RectSet(IdSet(7), Rect(22, 17, 24, 21)));
-  expected_out.emplace_back(RectSet(IdSet(7), Rect(24, 13, 26, 21)));
-  expected_out.emplace_back(RectSet(IdSet(9), Rect(30, 31, 32, 39)));
-  expected_out.emplace_back(RectSet(IdSet(8) | 9, Rect(32, 33, 36, 37)));
-  expected_out.emplace_back(RectSet(IdSet(9), Rect(32, 37, 36, 39)));
-  expected_out.emplace_back(RectSet(IdSet(9), Rect(32, 31, 36, 33)));
-  expected_out.emplace_back(RectSet(IdSet(9), Rect(36, 31, 38, 39)));
-  expected_out.emplace_back(RectSet(IdSet(10), Rect(40, 43, 44, 45)));
-  expected_out.emplace_back(RectSet(IdSet(10) | 11, Rect(44, 43, 46, 45)));
-  expected_out.emplace_back(RectSet(IdSet(11), Rect(44, 41, 46, 43)));
-  expected_out.emplace_back(RectSet(IdSet(11), Rect(44, 45, 46, 47)));
-  expected_out.emplace_back(RectSet(IdSet(10), Rect(46, 43, 48, 45)));
-  expected_out.emplace_back(RectSet(IdSet(12) | 13 | 14, Rect(50, 51, 52, 53)));
-
-  for (int i = 0; i < expected_out.size(); i++) {
-    RectSet &ex_out = expected_out[i];
-    if (std::find(out.begin(), out.end(), ex_out) == out.end()) {
-      std::cout << "Missing Rect: " << ex_out.id_set << "(" << ex_out.rect
-                << ")" << std::endl;
-    }
-  }
-
-  for (int i = 0; i < out.size(); i++) {
-    RectSet &actual_out = out[i];
-    if (std::find(expected_out.begin(), expected_out.end(), actual_out) ==
-        expected_out.end()) {
-      std::cout << "Extra Rect: " << actual_out.id_set << "(" << actual_out.rect
-                << ")" << std::endl;
-    }
-  }
-
-  return 0;
-}
-
-#endif
diff --git a/public/disjoint_layers.h b/public/disjoint_layers.h
new file mode 100644 (file)
index 0000000..edb8105
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+// Copyright (c) 2016 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef DISJOINT_LAYERS_H_
+#define DISJOINT_LAYERS_H_
+
+#include <stdint.h>
+
+#include <sstream>
+#include <vector>
+
+namespace hwcomposer {
+
+//Some of the structs are adopted from drm_hwcomposer
+template <typename TFloat>
+struct Rect {
+  union {
+    struct {
+      TFloat left, top, right, bottom;
+    };
+    struct {
+      TFloat x1, y1, x2, y2;
+    };
+    TFloat bounds[4];
+  };
+  typedef TFloat TNum;
+  Rect() {
+  }
+  Rect(TFloat xx1, TFloat yy1, TFloat xx2, TFloat yy2)
+      : x1(xx1), y1(yy1), x2(xx2), y2(yy2) {
+  }
+  template <typename T>
+  Rect(const Rect<T> &rhs) {
+    for (int i = 0; i < 4; i++)
+      bounds[i] = rhs.bounds[i];
+  }
+  template <typename T>
+  Rect<TFloat> &operator=(const Rect<T> &rhs) {
+    for (int i = 0; i < 4; i++)
+      bounds[i] = rhs.bounds[i];
+    return *this;
+  }
+  bool operator==(const Rect &rhs) const {
+    for (int i = 0; i < 4; i++) {
+      if (bounds[i] != rhs.bounds[i])
+        return false;
+    }
+    return true;
+  }
+  TFloat width() const {
+    return bounds[2] - bounds[0];
+  }
+  TFloat height() const {
+    return bounds[3] - bounds[1];
+  }
+  TFloat area() const {
+    return width() * height();
+  }
+  void Dump(std::ostringstream *out) const {
+    *out << "[x/y/w/h]=" << left << "/" << top << "/" << width() << "/"
+         << height();
+  }
+};
+struct RectIDs {
+ public:
+  typedef uint64_t TId;
+
+  RectIDs() : bitset(0) {
+  }
+
+  RectIDs(TId id) : bitset(0) {
+    add(id);
+  }
+
+  void add(TId id) {
+    bitset |= ((uint64_t)1) << id;
+  }
+
+  void subtract(TId id) {
+    bitset &= ~(((uint64_t)1) << id);
+  }
+
+  bool isEmpty() const {
+    return bitset == 0;
+  }
+
+  uint64_t getBits() const {
+    return bitset;
+  }
+
+  bool operator==(const RectIDs &rhs) const {
+    return bitset == rhs.bitset;
+  }
+
+  bool operator<(const RectIDs &rhs) const {
+    return bitset < rhs.bitset;
+  }
+
+  RectIDs operator|(const RectIDs &rhs) const {
+    RectIDs ret;
+    ret.bitset = bitset | rhs.bitset;
+    return ret;
+  }
+
+  RectIDs operator|(TId id) const {
+    RectIDs ret;
+    ret.bitset = bitset;
+    ret.add(id);
+    return ret;
+  }
+
+  static const int max_elements = sizeof(TId) * 8;
+
+ private:
+  uint64_t bitset;
+};
+
+template <typename TNum>
+struct RectSet {
+  RectIDs id_set;
+  Rect<TNum> rect;
+
+  RectSet(const RectIDs &i, const Rect<TNum> &r) : id_set(i), rect(r) {
+  }
+
+  bool operator==(const RectSet<TNum> &rhs) const {
+    return (id_set == rhs.id_set) && (rect == rhs.rect);
+  }
+};
+
+void get_draw_regions(const std::vector<Rect<int>> &in,
+                        std::vector<RectSet<int>> *out);
+}
+
+#endif
index 5ba4a2a..774deb4 100644 (file)
 
 #include <stdint.h>
 
-#include "separate_rects.h"
+#include "disjoint_layers.h"
 
 namespace hwcomposer {
 
 template <typename T>
-using HwcRect = separate_rects::Rect<T>;
+using HwcRect = Rect<T>;
 
 enum class HWCBlending : int32_t {
   kBlendingNone = 0x0100,
diff --git a/public/separate_rects.h b/public/separate_rects.h
deleted file mode 100644 (file)
index de8b660..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DRM_HWCOMPOSER_SEPARATE_RECTS_H_
-#define DRM_HWCOMPOSER_SEPARATE_RECTS_H_
-
-#include <stdint.h>
-
-#include <sstream>
-#include <vector>
-
-namespace separate_rects {
-
-template <typename TFloat>
-struct Rect {
-  union {
-    struct {
-      TFloat left, top, right, bottom;
-    };
-    struct {
-      TFloat x1, y1, x2, y2;
-    };
-    TFloat bounds[4];
-  };
-
-  typedef TFloat TNum;
-
-  Rect() {
-  }
-
-  Rect(TFloat xx1, TFloat yy1, TFloat xx2, TFloat yy2)
-      : x1(xx1), y1(yy1), x2(xx2), y2(yy2) {
-  }
-
-  template <typename T>
-  Rect(const Rect<T> &rhs) {
-    for (int i = 0; i < 4; i++)
-      bounds[i] = rhs.bounds[i];
-  }
-
-  template <typename T>
-  Rect<TFloat> &operator=(const Rect<T> &rhs) {
-    for (int i = 0; i < 4; i++)
-      bounds[i] = rhs.bounds[i];
-    return *this;
-  }
-
-  bool operator==(const Rect &rhs) const {
-    for (int i = 0; i < 4; i++) {
-      if (bounds[i] != rhs.bounds[i])
-        return false;
-    }
-
-    return true;
-  }
-
-  TFloat width() const {
-    return bounds[2] - bounds[0];
-  }
-
-  TFloat height() const {
-    return bounds[3] - bounds[1];
-  }
-
-  TFloat area() const {
-    return width() * height();
-  }
-
-  void Dump(std::ostringstream *out) const {
-    *out << "[x/y/w/h]=" << left << "/" << top << "/" << width() << "/"
-         << height();
-  }
-};
-
-template <typename TUInt>
-struct IdSet {
- public:
-  typedef TUInt TId;
-
-  IdSet() : bitset(0) {
-  }
-
-  IdSet(TId id) : bitset(0) {
-    add(id);
-  }
-
-  void add(TId id) {
-    bitset |= ((TUInt)1) << id;
-  }
-
-  void subtract(TId id) {
-    bitset &= ~(((TUInt)1) << id);
-  }
-
-  bool isEmpty() const {
-    return bitset == 0;
-  }
-
-  TUInt getBits() const {
-    return bitset;
-  }
-
-  bool operator==(const IdSet<TId> &rhs) const {
-    return bitset == rhs.bitset;
-  }
-
-  bool operator<(const IdSet<TId> &rhs) const {
-    return bitset < rhs.bitset;
-  }
-
-  IdSet<TId> operator|(const IdSet<TId> &rhs) const {
-    IdSet ret;
-    ret.bitset = bitset | rhs.bitset;
-    return ret;
-  }
-
-  IdSet<TId> operator|(TId id) const {
-    IdSet<TId> ret;
-    ret.bitset = bitset;
-    ret.add(id);
-    return ret;
-  }
-
-  static const int max_elements = sizeof(TId) * 8;
-
- private:
-  TUInt bitset;
-};
-
-template <typename TId, typename TNum>
-struct RectSet {
-  IdSet<TId> id_set;
-  Rect<TNum> rect;
-
-  RectSet(const IdSet<TId> &i, const Rect<TNum> &r) : id_set(i), rect(r) {
-  }
-
-  bool operator==(const RectSet<TId, TNum> &rhs) const {
-    return id_set == rhs.id_set && rect == rhs.rect;
-  }
-};
-
-// Separates up to a maximum of 64 input rectangles into mutually non-
-// overlapping rectangles that cover the exact same area and outputs those non-
-// overlapping rectangles. Each output rectangle also includes the set of input
-// rectangle indices that overlap the output rectangle encoded in a bitset. For
-// example, an output rectangle that overlaps input rectangles in[0], in[1], and
-// in[4], the bitset would be (ommitting leading zeroes) 10011.
-void separate_frects_64(const std::vector<Rect<float>> &in,
-                        std::vector<RectSet<uint64_t, float>> *out);
-void separate_rects_64(const std::vector<Rect<int>> &in,
-                       std::vector<RectSet<uint64_t, int>> *out);
-
-}  // namespace separate_rects
-
-#endif