Merge "drm_hwcomposer: Disable planes on frame failure" into mnc-dr-dev
diff --git a/autogl.h b/autogl.h
index 5eeca85..fc77fb0 100644
--- a/autogl.h
+++ b/autogl.h
@@ -52,8 +52,7 @@
 AUTO_GL_TYPE(AutoGLProgram, GLint, 0, glDeleteProgram(p))
 
 struct AutoEGLDisplayImage {
-  AutoEGLDisplayImage() : display_(EGL_NO_DISPLAY), image_(EGL_NO_IMAGE_KHR) {
-  }
+  AutoEGLDisplayImage() = default;
 
   AutoEGLDisplayImage(EGLDisplay display, EGLImageKHR image)
       : display_(display), image_(image) {
@@ -98,8 +97,8 @@
   }
 
  private:
-  EGLDisplay display_;
-  EGLImageKHR image_;
+  EGLDisplay display_ = EGL_NO_DISPLAY;
+  EGLImageKHR image_ = EGL_NO_IMAGE_KHR;
 };
 
 struct AutoEGLImageAndGLTexture {
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
index fdf389b..1490438 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -175,7 +175,7 @@
     return importer_ != NULL;
   }
 
-  hwc_drm_bo *operator->();
+  const hwc_drm_bo *operator->() const;
 
   void Clear();
 
@@ -257,11 +257,12 @@
   UniqueFd acquire_fence;
   OutputFd release_fence;
 
-  DrmHwcLayer() = default;
-  DrmHwcLayer(DrmHwcLayer &&rhs) = default;
-
   int InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
                        const gralloc_module_t *gralloc);
+
+  buffer_handle_t get_usable_handle() const {
+    return handle.get() != NULL ? handle.get() : sf_handle;
+  }
 };
 
 struct DrmHwcDisplayContents {
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index 55fa00c..4b293ee 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -58,10 +58,9 @@
     // If the display hasn't been modeset yet, this will be NULL
     DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
 
-    int ret = composition_map_[(*iter)->display()]->Init(drm_, crtc, importer_,
-                                                         frame_no);
+    int ret = composition_map_[display]->Init(drm_, crtc, importer_, frame_no);
     if (ret) {
-      ALOGE("Failed to init display composition for %d", (*iter)->display());
+      ALOGE("Failed to init display composition for %d", display);
       return ret;
     }
   }
diff --git a/drmcompositor.cpp b/drmcompositor.cpp
index ad4cf88..b486d7b 100644
--- a/drmcompositor.cpp
+++ b/drmcompositor.cpp
@@ -76,7 +76,7 @@
     int ret = compositor_map_[display].QueueComposition(
         composition->TakeDisplayComposition(display));
     if (ret) {
-      ALOGE("Failed to queue composition for display %d", display);
+      ALOGE("Failed to queue composition for display %d (%d)", display, ret);
       return ret;
     }
   }
diff --git a/glworker.cpp b/glworker.cpp
index ffb4182..162005c 100644
--- a/glworker.cpp
+++ b/glworker.cpp
@@ -176,54 +176,73 @@
   return shader;
 }
 
+static std::string GenerateVertexShader(int layer_count) {
+  std::ostringstream vertex_shader_stream;
+  vertex_shader_stream
+      << "#version 300 es\n"
+      << "#define LAYER_COUNT " << layer_count << "\n"
+      << "precision mediump int;\n"
+      << "uniform vec4 uViewport;\n"
+      << "uniform vec4 uLayerCrop[LAYER_COUNT];\n"
+      << "uniform mat2 uTexMatrix[LAYER_COUNT];\n"
+      << "in vec2 vPosition;\n"
+      << "in vec2 vTexCoords;\n"
+      << "out vec2 fTexCoords[LAYER_COUNT];\n"
+      << "void main() {\n"
+      << "  for (int i = 0; i < LAYER_COUNT; i++) {\n"
+      << "    vec2 tempCoords = vTexCoords * uTexMatrix[i];\n"
+      << "    fTexCoords[i] =\n"
+      << "        uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw;\n"
+      << "  }\n"
+      << "  vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw;\n"
+      << "  gl_Position =\n"
+      << "      vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0);\n"
+      << "}\n";
+  return vertex_shader_stream.str();
+}
+
+static std::string GenerateFragmentShader(int layer_count) {
+  std::ostringstream fragment_shader_stream;
+  fragment_shader_stream << "#version 300 es\n"
+                         << "#define LAYER_COUNT " << layer_count << "\n"
+                         << "#extension GL_OES_EGL_image_external : require\n"
+                         << "precision mediump float;\n";
+  for (int i = 0; i < layer_count; ++i) {
+    fragment_shader_stream << "uniform samplerExternalOES uLayerTexture" << i
+                           << ";\n";
+  }
+  fragment_shader_stream << "uniform float uLayerAlpha[LAYER_COUNT];\n"
+                         << "uniform float uLayerPremult[LAYER_COUNT];\n"
+                         << "in vec2 fTexCoords[LAYER_COUNT];\n"
+                         << "out vec4 oFragColor;\n"
+                         << "void main() {\n"
+                         << "  vec3 color = vec3(0.0, 0.0, 0.0);\n"
+                         << "  float alphaCover = 1.0;\n"
+                         << "  vec4 texSample;\n"
+                         << "  vec3 multRgb;\n";
+  for (int i = 0; i < layer_count; ++i) {
+    if (i > 0)
+      fragment_shader_stream << "  if (alphaCover > 0.5/255.0) {\n";
+    // clang-format off
+    fragment_shader_stream
+        << "  texSample = texture2D(uLayerTexture" << i << ",\n"
+        << "                        fTexCoords[" << i << "]);\n"
+        << "  multRgb = texSample.rgb *\n"
+        << "            max(texSample.a, uLayerPremult[" << i << "]);\n"
+        << "  color += multRgb * uLayerAlpha[" << i << "] * alphaCover;\n"
+        << "  alphaCover *= 1.0 - texSample.a * uLayerAlpha[" << i << "];\n";
+    // clang-format on
+  }
+  for (int i = 0; i < layer_count - 1; ++i)
+    fragment_shader_stream << "  }\n";
+  fragment_shader_stream << "  oFragColor = vec4(color, 1.0 - alphaCover);\n"
+                         << "}\n";
+  return fragment_shader_stream.str();
+}
+
 static int GenerateShaders(std::vector<AutoGLProgram> *blend_programs) {
   // Limits: GL_MAX_VARYING_COMPONENTS, GL_MAX_TEXTURE_IMAGE_UNITS,
   // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
-  // clang-format off
-  const GLchar *shader_preamble = "#version 300 es\n#define LAYER_COUNT ";
-
-  const GLchar *vertex_shader_source =
-"\n"
-"precision mediump int;                                                     \n"
-"uniform vec4 uViewport;                                                    \n"
-"uniform vec4 uLayerCrop[LAYER_COUNT];                                      \n"
-"uniform mat2 uTexMatrix[LAYER_COUNT];                                      \n"
-"in vec2 vPosition;                                                         \n"
-"in vec2 vTexCoords;                                                        \n"
-"out vec2 fTexCoords[LAYER_COUNT];                                          \n"
-"void main() {                                                              \n"
-"  for (int i = 0; i < LAYER_COUNT; i++) {                                  \n"
-"    vec2 tempCoords = vTexCoords * uTexMatrix[i];                          \n"
-"    fTexCoords[i] = uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw;      \n"
-"  }                                                                        \n"
-"  vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw;           \n"
-"  gl_Position = vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0);    \n"
-"}                                                                          \n";
-
-  const GLchar *fragment_shader_source =
-"\n"
-"#extension GL_OES_EGL_image_external : require                             \n"
-"precision mediump float;                                                   \n"
-"uniform samplerExternalOES uLayerTextures[LAYER_COUNT];                    \n"
-"uniform float uLayerAlpha[LAYER_COUNT];                                    \n"
-"uniform float uLayerPremult[LAYER_COUNT];                                  \n"
-"in vec2 fTexCoords[LAYER_COUNT];                                           \n"
-"out vec4 oFragColor;                                                       \n"
-"void main() {                                                              \n"
-"  vec3 color = vec3(0.0, 0.0, 0.0);                                        \n"
-"  float alphaCover = 1.0;                                                  \n"
-"  for (int i = 0; i < LAYER_COUNT; i++) {                                  \n"
-"    vec4 texSample = texture2D(uLayerTextures[i], fTexCoords[i]);          \n"
-"    float a = texSample.a * uLayerAlpha[i];                                \n"
-"    color += max(a, uLayerPremult[i]) * alphaCover * texSample.rgb;        \n"
-"    alphaCover *= 1.0 - a;                                                 \n"
-"    if (alphaCover <= 0.5/255.0)                                           \n"
-"      break;                                                               \n"
-"  }                                                                        \n"
-"  oFragColor = vec4(color, 1.0 - alphaCover);                              \n"
-"}                                                                          \n";
-  // clang-format on
-
   int i, ret = 1;
   GLint max_texture_images, status;
   AutoGLShader vertex_shader, fragment_shader;
@@ -233,27 +252,26 @@
   glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_images);
 
   for (i = 1; i <= max_texture_images; i++) {
-    std::ostringstream layer_count_formatter;
-    layer_count_formatter << i;
-    std::string layer_count(layer_count_formatter.str());
-    const GLchar *shader_sources[3] = {shader_preamble, layer_count.c_str(),
-                                       NULL};
-
-    shader_sources[2] = vertex_shader_source;
-    vertex_shader = CompileAndCheckShader(GL_VERTEX_SHADER, 3, shader_sources,
-                                          ret ? &shader_log : NULL);
+    std::string vertex_shader_string = GenerateVertexShader(i);
+    const GLchar *vertex_shader_source = vertex_shader_string.c_str();
+    vertex_shader = CompileAndCheckShader(
+        GL_VERTEX_SHADER, 1, &vertex_shader_source, ret ? &shader_log : NULL);
     if (!vertex_shader.get()) {
       if (ret)
-        ALOGE("Failed to make vertex shader:\n%s", shader_log.c_str());
+        ALOGE("Failed to make vertex shader:\n%sshader source:\n%s",
+              shader_log.c_str(), vertex_shader_source);
       break;
     }
 
-    shader_sources[2] = fragment_shader_source;
-    fragment_shader = CompileAndCheckShader(
-        GL_FRAGMENT_SHADER, 3, shader_sources, ret ? &shader_log : NULL);
+    std::string fragment_shader_string = GenerateFragmentShader(i);
+    const GLchar *fragment_shader_source = fragment_shader_string.c_str();
+    fragment_shader =
+        CompileAndCheckShader(GL_FRAGMENT_SHADER, 1, &fragment_shader_source,
+                              ret ? &shader_log : NULL);
     if (!fragment_shader.get()) {
       if (ret)
-        ALOGE("Failed to make fragment shader:\n%s", shader_log.c_str());
+        ALOGE("Failed to make fragment shader:\n%sshader source:\n%s",
+              shader_log.c_str(), fragment_shader_source);
       break;
     }
 
@@ -419,7 +437,8 @@
         }
 
         src.alpha = layer.alpha / 255.0f;
-        src.premult = (layer.blending == DrmHwcBlending::kPreMult) ? 1.0f : 0.0f;
+        src.premult =
+            (layer.blending == DrmHwcBlending::kPreMult) ? 1.0f : 0.0f;
       }
     }
   }
@@ -652,7 +671,6 @@
     GLint program = blend_programs_[cmd.texture_count - 1].get();
     glUseProgram(program);
     GLint gl_viewport_loc = glGetUniformLocation(program, "uViewport");
-    GLint gl_tex_loc = glGetUniformLocation(program, "uLayerTextures");
     GLint gl_crop_loc = glGetUniformLocation(program, "uLayerCrop");
     GLint gl_alpha_loc = glGetUniformLocation(program, "uLayerAlpha");
     GLint gl_premult_loc = glGetUniformLocation(program, "uLayerPremult");
@@ -663,13 +681,18 @@
                 (cmd.bounds[3] - cmd.bounds[1]) / (float)frame_height);
 
     for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
+      std::ostringstream texture_name_formatter;
+      texture_name_formatter << "uLayerTexture" << src_index;
+      GLint gl_tex_loc =
+          glGetUniformLocation(program, texture_name_formatter.str().c_str());
+
       const RenderingCommand::TextureSource &src = cmd.textures[src_index];
       glUniform1f(gl_alpha_loc + src_index, src.alpha);
       glUniform1f(gl_premult_loc + src_index, src.premult);
       glUniform4f(gl_crop_loc + src_index, src.crop_bounds[0],
                   src.crop_bounds[1], src.crop_bounds[2] - src.crop_bounds[0],
                   src.crop_bounds[3] - src.crop_bounds[1]);
-      glUniform1i(gl_tex_loc + src_index, src_index);
+      glUniform1i(gl_tex_loc, src_index);
       glUniformMatrix2fv(gl_tex_matrix_loc + src_index, 1, GL_FALSE,
                          src.texture_matrix);
       glActiveTexture(GL_TEXTURE0 + src_index);
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index a7c9e43..6a0f4cd 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -191,9 +191,9 @@
   return *this;
 }
 
-hwc_drm_bo *DrmHwcBuffer::operator->() {
+const hwc_drm_bo *DrmHwcBuffer::operator->() const {
   if (importer_ == NULL) {
-    ALOGE("Access of none existent BO");
+    ALOGE("Access of non-existent BO");
     exit(1);
     return NULL;
   }
@@ -264,16 +264,15 @@
 int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
                                   const gralloc_module_t *gralloc) {
   sf_handle = sf_layer->handle;
-  int ret = buffer.ImportBuffer(sf_layer->handle, importer);
-  if (ret)
-    return ret;
-
-  ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
-  if (ret)
-    return ret;
-
   alpha = sf_layer->planeAlpha;
 
+  source_crop = DrmHwcRect<float>(
+      sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
+      sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
+  display_frame = DrmHwcRect<int>(
+      sf_layer->displayFrame.left, sf_layer->displayFrame.top,
+      sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+
   switch (sf_layer->transform) {
     case 0:
       transform = DrmHwcTransform::kIdentity;
@@ -313,12 +312,13 @@
       return -EINVAL;
   }
 
-  source_crop = DrmHwcRect<float>(
-      sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
-      sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
-  display_frame = DrmHwcRect<int>(
-      sf_layer->displayFrame.left, sf_layer->displayFrame.top,
-      sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+  int ret = buffer.ImportBuffer(sf_layer->handle, importer);
+  if (ret)
+    return ret;
+
+  ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
+  if (ret)
+    return ret;
 
   return 0;
 }
@@ -501,13 +501,18 @@
 
     layers_map.emplace_back();
     DrmCompositionDisplayLayersMap &map = layers_map.back();
+    map.display = i;
     std::vector<size_t> &indices_to_composite = layers_indices[i];
     for (size_t j : indices_to_composite) {
       hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
 
       DrmHwcLayer &layer = display_contents.layers[j];
 
-      layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+      ret = layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+      if (ret) {
+        ALOGE("Failed to init composition from layer %d", ret);
+        return ret;
+      }
       map.layers.emplace_back(std::move(layer));
     }
   }
diff --git a/seperate_rects.cpp b/seperate_rects.cpp
index bdf07bc..06fbe39 100644
--- a/seperate_rects.cpp
+++ b/seperate_rects.cpp
@@ -71,8 +71,8 @@
 }
 
 template <typename TNum, typename TId>
-void seperate_rects(const std::vector<Rect<TNum> > &in,
-                    std::vector<RectSet<TId, TNum> > *out) {
+void seperate_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
@@ -91,8 +91,8 @@
 
   // 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
+  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
@@ -102,7 +102,7 @@
 
   // 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;
+  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.
@@ -120,7 +120,7 @@
     sweep_h_events.insert(evt);
   }
 
-  for (typename std::set<SweepEvent<TId, TNum> >::iterator it =
+  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;
@@ -142,14 +142,14 @@
     } else {
       v_evt.type = START;
       v_evt.y = rect.top;
-      typename std::set<SweepEvent<TId, TNum> >::iterator start_it =
+      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 =
+      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);
@@ -159,7 +159,7 @@
     // 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;
+    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) {
@@ -179,7 +179,7 @@
     // 5), active_regions will be [({ 0 }, 3), {}, 5].
     active_regions.clear();
     IdSet<TId> active_set;
-    for (typename std::set<SweepEvent<TId, TNum> >::iterator it =
+    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;
@@ -199,7 +199,7 @@
 
 #ifdef RECTS_DEBUG
     std::cout << "x:" << h_evt.x;
-    for (std::vector<std::pair<TNum, IdSet> >::iterator it =
+    for (std::vector<std::pair<TNum, IdSet>>::iterator it =
              active_regions.begin();
          it != active_regions.end(); ++it) {
       std::cout << " " << it->first << "(" << it->second << ")"
@@ -226,7 +226,7 @@
     // 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 =
+    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;
@@ -237,8 +237,7 @@
       // 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;
+      typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator next_it = it;
       ++next_it;
       assert(next_it != active_regions.end());
 
@@ -300,8 +299,13 @@
   }
 }
 
-void seperate_frects_64(const std::vector<Rect<float> > &in,
-                        std::vector<RectSet<uint64_t, float> > *out) {
+void seperate_frects_64(const std::vector<Rect<float>> &in,
+                        std::vector<RectSet<uint64_t, float>> *out) {
+  seperate_rects(in, out);
+}
+
+void seperate_rects_64(const std::vector<Rect<int>> &in,
+                       std::vector<RectSet<uint64_t, int>> *out) {
   seperate_rects(in, out);
 }
 
diff --git a/seperate_rects.h b/seperate_rects.h
index 540a5e8..1e0a267 100644
--- a/seperate_rects.h
+++ b/seperate_rects.h
@@ -64,6 +64,18 @@
 
     return true;
   }
+
+  TFloat width() const {
+    return bounds[2] - bounds[0];
+  }
+
+  TFloat height() const {
+    return bounds[3] - bounds[1];
+  }
+
+  TFloat area() const {
+    return width() * height();
+  }
 };
 
 template <typename TUInt>
@@ -140,8 +152,10 @@
 // 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 seperate_frects_64(const std::vector<Rect<float> > &in,
-                        std::vector<RectSet<uint64_t, float> > *out);
+void seperate_frects_64(const std::vector<Rect<float>> &in,
+                        std::vector<RectSet<uint64_t, float>> *out);
+void seperate_rects_64(const std::vector<Rect<int>> &in,
+                       std::vector<RectSet<uint64_t, int>> *out);
 
 }  // namespace seperate_rects