OSDN Git Service

Android: Add HWC 1.5 support.
authorKalyan Kondapally <kalyan.kondapally@intel.com>
Sat, 22 Jul 2017 08:15:44 +0000 (04:15 -0400)
committerKalyan Kondapally <kalyan.kondapally@intel.com>
Sat, 22 Jul 2017 09:00:13 +0000 (05:00 -0400)
We want to enable Android M support but M only supports
version <2.0 HWC. Let's enable support for HWC 1.5.
Support is enabled only if BOARD_USES_HWC1 is set to
true in BoardConfig.

Jira: None.
Test: System boots up to Home screen.

Signed-off-by: Kalyan Kondapally <kalyan.kondapally@intel.com>
Signed-off-by: Harish Krupo <harish.krupo.kps@intel.com>
Android.mk
os/android/iahwc1.cpp [new file with mode: 0644]
wsi/drm/drmdisplay.cpp

index 1c7f732..4d26eaa 100644 (file)
@@ -32,7 +32,7 @@ LOCAL_SHARED_LIBRARIES := \
        liblog \
        libui \
        libutils \
-       libhwcservice \
+        libhwcservice \
        libbinder
 
 LOCAL_C_INCLUDES := \
@@ -73,10 +73,21 @@ LOCAL_SRC_FILES := \
        wsi/drm/drmplane.cpp \
        wsi/drm/drmdisplaymanager.cpp \
        wsi/drm/drmscopedtypes.cpp \
-        os/android/iahwc2.cpp \
-        os/android/hwcservice.cpp \
         os/android/multidisplaymanager.cpp
 
+ifeq ($(strip $(BOARD_USES_HWC1)), true)
+LOCAL_SRC_FILES += os/android/iahwc1.cpp
+LOCAL_C_INCLUDES += \
+        system/core/libsync \
+        system/core/libsync/include
+
+LOCAL_SHARED_LIBRARIES += \
+        libsync
+else
+LOCAL_SRC_FILES += os/android/iahwc2.cpp \
+                   os/android/hwcservice.cpp
+endif
+
 ifeq ($(strip $(BOARD_USES_GRALLOC1)), true)
 LOCAL_SRC_FILES += os/android/gralloc1bufferhandler.cpp
 else
@@ -132,6 +143,7 @@ LOCAL_MODULE_CLASS := SHARED_LIBRARIES
 LOCAL_MODULE_SUFFIX := $(TARGET_SHLIB_SUFFIX)
 include $(BUILD_SHARED_LIBRARY)
 
+ifneq ($(strip $(BOARD_USES_HWC1)), true)
 # libhwcservice
 HWC_BUILD_DIRS := \
 $(LOCAL_PATH)/os/android/libhwcservice/Android.mk \
@@ -141,8 +153,14 @@ include $(HWC_BUILD_DIRS)
 
 #Include tests only if eng build
 ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
-# Commenting for now include when ld issue is resolved
 include $(HWC_PATH)/tests/hwc-val/tests/hwc/Android.mk
+endif
+
+endif
+
+#Include tests only if eng build
+ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
+# Commenting for now include when ld issue is resolved
 #include $(LOCAL_PATH)/tests/third_party/json-c/Android.mk
 endif
 
diff --git a/os/android/iahwc1.cpp b/os/android/iahwc1.cpp
new file mode 100644 (file)
index 0000000..05c0c5c
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <inttypes.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <sw_sync.h>
+#include <sync/sync.h>
+
+#include <gpudevice.h>
+#include <hwclayer.h>
+#include <platformdefines.h>
+#include <hwcdefs.h>
+#include <nativedisplay.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+
+#include "utils_android.h"
+
+namespace android {
+
+class DisplayTimeLine {
+ public:
+  int Init() {
+    timeline_fd_ = open("/dev/sw_sync", O_RDWR);
+    if (timeline_fd_ < 0)
+      return -1;
+
+    return 0;
+  }
+
+  ~DisplayTimeLine() {
+    if (timeline_fd_ > 0) {
+      close(timeline_fd_);
+    }
+  }
+
+  int32_t IncrementTimeLine() {
+    int ret =
+        sw_sync_fence_create(timeline_fd_, "dummy fence", timeline_pt_ + 1);
+    if (ret < 0) {
+      ALOGE("Failed to create dummy fence %d %d", ret, timeline_fd_);
+      return ret;
+    }
+
+    int32_t ret_fd(ret);
+
+    ret = sw_sync_timeline_inc(timeline_fd_, 1);
+    if (ret) {
+      ALOGE("Failed to increment dummy sync timeline %d", ret);
+      return ret;
+    }
+
+    ++timeline_pt_;
+    return ret_fd;
+  }
+
+ private:
+  int32_t timeline_fd_;
+  int timeline_pt_ = 0;
+};
+
+struct IAHwc1Layer {
+  ~IAHwc1Layer() {
+    delete hwc_layer_;
+    hwc_layer_ = NULL;
+  }
+
+  struct gralloc_handle native_handle_;
+  hwcomposer::HwcLayer *hwc_layer_ = NULL;
+  uint32_t index_ = 0;
+
+  int InitFromHwcLayer(hwc_layer_1_t *sf_layer);
+};
+
+typedef struct HwcDisplay {
+  struct hwc_context_t *ctx;
+  hwcomposer::NativeDisplay *display_ = NULL;
+  uint32_t display_id_ = 0;
+  int32_t fence_ = -1;
+  int last_render_layers_size = -1;
+  std::vector<IAHwc1Layer *> layers_;
+  DisplayTimeLine timeline_;
+
+} hwc_drm_display_t;
+
+struct hwc_context_t {
+  ~hwc_context_t() {
+  }
+
+  hwc_composer_device_1_t device;
+  hwc_procs_t const *procs = NULL;
+
+  hwcomposer::GpuDevice device_;
+  std::vector<HwcDisplay> extended_displays_;
+  HwcDisplay primary_display_;
+  HwcDisplay virtual_display_;
+
+  bool disable_explicit_sync_ = false;
+};
+
+class IAVsyncCallback : public hwcomposer::VsyncCallback {
+ public:
+  IAVsyncCallback(hwc_procs_t const *procs) : procs_(procs) {
+  }
+
+  void Callback(uint32_t display, int64_t timestamp) {
+    procs_->vsync(procs_, display > 0 ? HWC_DISPLAY_EXTERNAL_BIT
+                                      : HWC_DISPLAY_PRIMARY_BIT,
+                  timestamp);
+  }
+
+ private:
+  hwc_procs_t const *procs_;
+};
+
+class IAHotPlugEventCallback : public hwcomposer::HotPlugCallback {
+ public:
+  IAHotPlugEventCallback(hwc_procs_t const *procs) : procs_(procs) {
+  }
+
+  void Callback(uint32_t /*display*/, bool connected) {
+    if (ignore_) {
+      ignore_ = false;
+      return;
+    }
+
+    procs_->hotplug(procs_, HWC_DISPLAY_EXTERNAL_BIT, connected);
+  }
+
+ private:
+  hwc_procs_t const *procs_;
+  bool ignore_ = true;
+};
+
+class IARefreshCallback : public hwcomposer::RefreshCallback {
+ public:
+  IARefreshCallback(hwc_procs_t const *procs) : procs_(procs) {
+  }
+
+  void Callback(uint32_t /*display*/) {
+    procs_->invalidate(procs_);
+  }
+
+ private:
+  hwc_procs_t const *procs_;
+};
+
+int IAHwc1Layer::InitFromHwcLayer(hwc_layer_1_t *sf_layer) {
+  if (!hwc_layer_) {
+    hwc_layer_ = new hwcomposer::HwcLayer();
+  }
+
+  native_handle_.handle_ = sf_layer->handle;
+  hwc_layer_->SetNativeHandle(&native_handle_);
+  hwc_layer_->SetAlpha(sf_layer->planeAlpha);
+  hwc_layer_->SetSourceCrop(hwcomposer::HwcRect<float>(
+      sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
+      sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom));
+  hwc_layer_->SetDisplayFrame(hwcomposer::HwcRect<int>(
+      sf_layer->displayFrame.left, sf_layer->displayFrame.top,
+      sf_layer->displayFrame.right, sf_layer->displayFrame.bottom));
+
+  uint32_t transform = 0;
+  if (sf_layer->transform == HWC_TRANSFORM_ROT_270) {
+    transform = hwcomposer::HWCTransform::kRotate270;
+  } else if (sf_layer->transform == HWC_TRANSFORM_ROT_180) {
+    transform = hwcomposer::HWCTransform::kRotate180;
+  } else {
+    if (sf_layer->transform & HWC_TRANSFORM_FLIP_H)
+      transform |= hwcomposer::HWCTransform::kReflectX;
+    if (sf_layer->transform & HWC_TRANSFORM_FLIP_V)
+      transform |= hwcomposer::HWCTransform::kReflectY;
+    if (sf_layer->transform & HWC_TRANSFORM_ROT_90)
+      transform |= hwcomposer::HWCTransform::kRotate90;
+  }
+
+  hwc_layer_->SetTransform(transform);
+  hwc_layer_->SetAcquireFence(dup(sf_layer->acquireFenceFd));
+
+  switch (sf_layer->blending) {
+    case HWC_BLENDING_NONE:
+      hwc_layer_->SetBlending(hwcomposer::HWCBlending::kBlendingNone);
+      break;
+    case HWC_BLENDING_PREMULT:
+      hwc_layer_->SetBlending(hwcomposer::HWCBlending::kBlendingPremult);
+      break;
+    case HWC_BLENDING_COVERAGE:
+      hwc_layer_->SetBlending(hwcomposer::HWCBlending::kBlendingCoverage);
+      break;
+    default:
+      ALOGE("Invalid blending in hwc_layer_1_t %d", sf_layer->blending);
+      return -EINVAL;
+  }
+
+  uint32_t num_rects = sf_layer->surfaceDamage.numRects;
+  hwcomposer::HwcRegion hwc_region;
+
+  for (size_t rect = 0; rect < num_rects; ++rect) {
+    hwc_region.emplace_back(sf_layer->surfaceDamage.rects[rect].left,
+                            sf_layer->surfaceDamage.rects[rect].top,
+                            sf_layer->surfaceDamage.rects[rect].right,
+                            sf_layer->surfaceDamage.rects[rect].bottom);
+  }
+
+  num_rects = sf_layer->visibleRegionScreen.numRects;
+  hwcomposer::HwcRegion visible_region;
+
+  for (size_t rect = 0; rect < num_rects; ++rect) {
+    visible_region.emplace_back(
+        sf_layer->visibleRegionScreen.rects[rect].left,
+        sf_layer->visibleRegionScreen.rects[rect].top,
+        sf_layer->visibleRegionScreen.rects[rect].right,
+        sf_layer->visibleRegionScreen.rects[rect].bottom);
+  }
+
+  hwc_layer_->SetVisibleRegion(visible_region);
+  hwc_layer_->SetSurfaceDamage(hwc_region);
+  return 0;
+}
+
+static void hwc_dump(struct hwc_composer_device_1 * /*dev*/, char * /*buff*/,
+                     int /*buff_len*/) {
+}
+
+static bool hwc_skip_layer(const std::pair<int, int> &indices, int i) {
+  return indices.first >= 0 && i >= indices.first && i <= indices.second;
+}
+
+static HwcDisplay *GetDisplay(struct hwc_context_t *ctx, int display) {
+  if (display == 0) {
+    return &ctx->primary_display_;
+  }
+
+  if (display == HWC_DISPLAY_VIRTUAL) {
+    return &ctx->virtual_display_;
+  }
+
+  return &ctx->extended_displays_.at(0);
+}
+
+static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
+                       hwc_display_contents_1_t **display_contents) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  int total_displays = (int)num_displays;
+  for (int i = 0; i < total_displays; ++i) {
+    if (!display_contents[i])
+      continue;
+    bool use_framebuffer_target = false;
+#ifdef USE_DISABLE_OVERLAY_USAGE
+    use_framebuffer_target = true;
+#endif
+    if (i == HWC_DISPLAY_VIRTUAL) {
+      use_framebuffer_target = true;
+    }
+
+    std::pair<int, int> skip_layer_indices(-1, -1);
+    int num_layers = display_contents[i]->numHwLayers;
+    for (int j = 0; !use_framebuffer_target && j < num_layers; ++j) {
+      hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
+
+      if (!(layer->flags & HWC_SKIP_LAYER))
+        continue;
+
+      if (skip_layer_indices.first == -1)
+        skip_layer_indices.first = j;
+      skip_layer_indices.second = j;
+    }
+
+    for (int j = 0; j < num_layers; ++j) {
+      hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
+
+      if (!use_framebuffer_target && !hwc_skip_layer(skip_layer_indices, j)) {
+        HwcDisplay *native_display = GetDisplay(ctx, i);
+        hwcomposer::NativeDisplay *display = native_display->display_;
+
+        const hwc_rect_t *frame = &layer->displayFrame;
+        if ((frame->right - frame->left) <= 0 ||
+            (frame->bottom - frame->top) <= 0 || frame->right <= 0 ||
+            frame->bottom <= 0 || frame->left >= (int)display->Width() ||
+            frame->top >= (int)display->Height())
+          continue;
+
+        if (layer->compositionType == HWC_FRAMEBUFFER)
+          layer->compositionType = HWC_OVERLAY;
+      } else {
+        switch (layer->compositionType) {
+          case HWC_OVERLAY:
+          case HWC_BACKGROUND:
+          case HWC_SIDEBAND:
+          case HWC_CURSOR_OVERLAY:
+            layer->compositionType = HWC_FRAMEBUFFER;
+            break;
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
+                   hwc_display_contents_1_t **sf_display_contents) {
+  ATRACE_CALL();
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  for (size_t i = 0; i < num_displays; ++i) {
+    hwc_display_contents_1_t *dc = sf_display_contents[i];
+    if (!sf_display_contents[i] || i == HWC_DISPLAY_VIRTUAL)
+      continue;
+
+    size_t num_dc_layers = dc->numHwLayers;
+    HwcDisplay *native_display = GetDisplay(ctx, i);
+    hwcomposer::NativeDisplay *display = native_display->display_;
+    std::vector<IAHwc1Layer *> &old_layers = native_display->layers_;
+    std::vector<IAHwc1Layer *> new_layers;
+    size_t size = old_layers.size();
+    std::vector<hwcomposer::HwcLayer *> source_layers;
+    for (size_t j = 0; j < num_dc_layers; ++j) {
+      hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
+      if (!sf_layer || !sf_layer->handle || (sf_layer->flags & HWC_SKIP_LAYER))
+        continue;
+
+      IAHwc1Layer *new_layer = new IAHwc1Layer();
+      if (size > j) {
+        IAHwc1Layer *old_layer = old_layers.at(j);
+        new_layer->hwc_layer_ = old_layer->hwc_layer_;
+        old_layer->hwc_layer_ = NULL;
+      }
+
+      new_layer->InitFromHwcLayer(sf_layer);
+      source_layers.emplace_back(new_layer->hwc_layer_);
+      new_layer->index_ = j;
+      new_layers.emplace_back(new_layer);
+      sf_layer->acquireFenceFd = -1;
+    }
+
+    if (source_layers.empty())
+      return 0;
+
+    int32_t retire_fence = -1;
+    old_layers.swap(new_layers);
+    size = new_layers.size();
+    for (size_t i = 0; i < size; i++) {
+      IAHwc1Layer *layer = new_layers.at(i);
+      delete layer;
+    }
+
+    bool success = display->Present(source_layers, &retire_fence);
+    if (!success) {
+      ALOGE("Failed to set layers in the composition");
+      return -1;
+    }
+
+    if (retire_fence > 0)
+      close(retire_fence);
+
+    std::vector<hwcomposer::HwcLayer *>().swap(source_layers);
+  }
+
+  for (size_t i = 0; i < num_displays; ++i) {
+    hwc_display_contents_1_t *dc = sf_display_contents[i];
+    if (!dc)
+      continue;
+
+    HwcDisplay *native_display = GetDisplay(ctx, i);
+    std::vector<IAHwc1Layer *> &layers = native_display->layers_;
+    size_t size = layers.size();
+    if (size == 0)
+      continue;
+
+    for (size_t i = 0; i < size; i++) {
+      hwcomposer::HwcLayer *layer = layers.at(i)->hwc_layer_;
+      int32_t release_fence = layer->GetReleaseFence();
+      if (release_fence <= 0)
+        continue;
+
+      hwc_layer_1_t *sf_layer = &dc->hwLayers[layers.at(i)->index_];
+      sf_layer->releaseFenceFd = release_fence;
+    }
+
+    dc->retireFenceFd = native_display->timeline_.IncrementTimeLine();
+  }
+
+  return 0;
+}
+
+static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
+                             int event, int enabled) {
+  if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
+    return -EINVAL;
+
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  HwcDisplay *native_display = GetDisplay(ctx, display);
+  hwcomposer::NativeDisplay *temp = native_display->display_;
+  temp->VSyncControl(enabled);
+  return 0;
+}
+
+static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
+                              int mode) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  uint32_t power_mode = hwcomposer::kOn;
+  switch (mode) {
+    case HWC_POWER_MODE_OFF:
+      power_mode = hwcomposer::kOff;
+      break;
+    case HWC_POWER_MODE_DOZE:
+      power_mode = hwcomposer::kDoze;
+      break;
+    case HWC_POWER_MODE_DOZE_SUSPEND:
+      power_mode = hwcomposer::kDozeSuspend;
+      break;
+    case HWC_POWER_MODE_NORMAL:
+      power_mode = hwcomposer::kOn;
+      break;
+    default:
+      ALOGI("Power mode %d is unsupported\n", mode);
+      return -1;
+  };
+
+  HwcDisplay *native_display = GetDisplay(ctx, display);
+  hwcomposer::NativeDisplay *temp = native_display->display_;
+  temp->SetPowerMode(power_mode);
+  return 0;
+}
+
+static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
+                     int *value) {
+  switch (what) {
+    case HWC_BACKGROUND_LAYER_SUPPORTED:
+      *value = 0;
+      break;
+    case HWC_VSYNC_PERIOD:
+      *value = 1000 * 1000 * 1000 / 60;
+      break;
+    case HWC_DISPLAY_TYPES_SUPPORTED:
+      *value = HWC_DISPLAY_PRIMARY_BIT | HWC_DISPLAY_EXTERNAL_BIT |
+               HWC_DISPLAY_VIRTUAL_BIT;
+      break;
+  }
+  return 0;
+}
+
+static void hwc_register_procs(struct hwc_composer_device_1 *dev,
+                               hwc_procs_t const *procs) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  hwcomposer::NativeDisplay *display = ctx->primary_display_.display_;
+
+  ctx->procs = procs;
+
+  auto callback = std::make_shared<IAVsyncCallback>(procs);
+  display->RegisterVsyncCallback(std::move(callback), 0);
+
+  auto refresh_callback = std::make_shared<IARefreshCallback>(procs);
+  display->RegisterRefreshCallback(std::move(refresh_callback),
+                                   static_cast<int>(0));
+
+  std::vector<HwcDisplay> &extended = ctx->extended_displays_;
+  size_t size = extended.size();
+  for (size_t i = 0; i < size; i++) {
+    auto extended_callback = std::make_shared<IAVsyncCallback>(procs);
+    extended.at(i)
+        .display_->RegisterVsyncCallback(std::move(extended_callback), 1);
+
+    auto extended_hot_plug_callback =
+        std::make_shared<IAHotPlugEventCallback>(procs);
+    extended.at(i).display_->RegisterHotPlugCallback(
+        std::move(extended_hot_plug_callback), 1);
+
+    auto extended_refresh_callback = std::make_shared<IARefreshCallback>(procs);
+    extended.at(i).display_->RegisterRefreshCallback(
+        std::move(extended_refresh_callback), static_cast<int>(1));
+  }
+}
+
+static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
+                                   int display, uint32_t *configs,
+                                   size_t *num_configs) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  uint32_t size = 0;
+  HwcDisplay *native_display = GetDisplay(ctx, display);
+  hwcomposer::NativeDisplay *temp = native_display->display_;
+
+  if (!temp->GetDisplayConfigs(&size, configs))
+    return -1;
+
+  *num_configs = size;
+
+  return *num_configs == 0 ? -1 : 0;
+}
+
+static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
+                                      int display, uint32_t config,
+                                      const uint32_t *attributes,
+                                      int32_t *values) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  HwcDisplay *native_display = GetDisplay(ctx, display);
+  hwcomposer::NativeDisplay *temp = native_display->display_;
+  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
+    switch (attributes[i]) {
+      case HWC_DISPLAY_WIDTH:
+        temp->GetDisplayAttribute(
+            config, hwcomposer::HWCDisplayAttribute::kWidth, &values[i]);
+        break;
+      case HWC_DISPLAY_HEIGHT:
+        temp->GetDisplayAttribute(
+            config, hwcomposer::HWCDisplayAttribute::kHeight, &values[i]);
+        break;
+      case HWC_DISPLAY_VSYNC_PERIOD:
+        // in nanoseconds
+        temp->GetDisplayAttribute(
+            config, hwcomposer::HWCDisplayAttribute::kRefreshRate, &values[i]);
+        break;
+      case HWC_DISPLAY_DPI_X:
+        // Dots per 1000 inches
+        temp->GetDisplayAttribute(
+            config, hwcomposer::HWCDisplayAttribute::kDpiX, &values[i]);
+        break;
+      case HWC_DISPLAY_DPI_Y:
+        // Dots per 1000 inches
+        temp->GetDisplayAttribute(
+            config, hwcomposer::HWCDisplayAttribute::kDpiY, &values[i]);
+        break;
+      default:
+        values[i] = -1;
+        return -1;
+    }
+  }
+
+  return 0;
+}
+
+static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
+                                 int display) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  uint32_t config;
+  HwcDisplay *native_display = GetDisplay(ctx, display);
+  hwcomposer::NativeDisplay *temp = native_display->display_;
+
+  if (!temp->GetActiveConfig(&config))
+    return -1;
+
+  return config;
+}
+
+static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
+                                 int index) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  HwcDisplay *native_display = GetDisplay(ctx, display);
+  hwcomposer::NativeDisplay *temp = native_display->display_;
+
+  temp->SetActiveConfig(index);
+  return 0;
+}
+
+static int hwc_device_close(struct hw_device_t *dev) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
+  delete ctx;
+  return 0;
+}
+
+static int hwc_device_open(const struct hw_module_t *module, const char *name,
+                           struct hw_device_t **dev) {
+  if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
+    ALOGE("Invalid module name- %s", name);
+    return -EINVAL;
+  }
+
+  std::unique_ptr<hwc_context_t> ctx(new hwc_context_t());
+  if (!ctx) {
+    ALOGE("Failed to allocate hwc context");
+    return -ENOMEM;
+  }
+
+  char value[PROPERTY_VALUE_MAX];
+  property_get("board.disable.explicit.sync", value, "0");
+  ctx->disable_explicit_sync_ = atoi(value);
+  if (ctx->disable_explicit_sync_)
+    ALOGI("EXPLICIT SYNC support is disabled");
+  else
+    ALOGI("EXPLICIT SYNC support is enabled");
+
+  if (!ctx->device_.Initialize()) {
+    ALOGE("Can't initialize drm object.");
+    return -1;
+  }
+
+  std::vector<hwcomposer::NativeDisplay *> displays =
+      ctx->device_.GetAllDisplays();
+  ctx->virtual_display_.display_ = ctx->device_.GetVirtualDisplay();
+  ctx->virtual_display_.display_->SetExplicitSyncSupport(
+      ctx->disable_explicit_sync_);
+  ctx->virtual_display_.timeline_.Init();
+
+  size_t size = displays.size();
+  hwcomposer::NativeDisplay *primary_display = displays.at(0);
+  ctx->primary_display_.display_ = primary_display;
+  ctx->primary_display_.display_id_ = 0;
+  ctx->primary_display_.display_->SetExplicitSyncSupport(
+      ctx->disable_explicit_sync_);
+  ctx->primary_display_.timeline_.Init();
+  // Fetch the number of modes from the display
+  uint32_t num_configs;
+  uint32_t default_config;
+  if (!primary_display->GetDisplayConfigs(&num_configs, NULL))
+    return -1;
+
+  // Grab the first mode, we'll choose this as the active mode
+  num_configs = 1;
+  if (!primary_display->GetDisplayConfigs(&num_configs, &default_config))
+    return -1;
+
+  if (!primary_display->SetActiveConfig(default_config)) {
+    ALOGE("Could not find active mode for %d", default_config);
+    return -1;
+  }
+
+  for (size_t i = 1; i < size; ++i) {
+    ctx->extended_displays_.emplace_back();
+    HwcDisplay &temp = ctx->extended_displays_.back();
+    temp.display_ = displays.at(i);
+    temp.display_id_ = i;
+    temp.timeline_.Init();
+    temp.display_->SetExplicitSyncSupport(ctx->disable_explicit_sync_);
+  }
+
+  ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+  ctx->device.common.version = HWC_DEVICE_API_VERSION_1_5;
+  ctx->device.common.module = const_cast<hw_module_t *>(module);
+  ctx->device.common.close = hwc_device_close;
+
+  ctx->device.dump = hwc_dump;
+  ctx->device.prepare = hwc_prepare;
+  ctx->device.set = hwc_set;
+  ctx->device.eventControl = hwc_event_control;
+  ctx->device.setPowerMode = hwc_set_power_mode;
+  ctx->device.query = hwc_query;
+  ctx->device.registerProcs = hwc_register_procs;
+  ctx->device.getDisplayConfigs = hwc_get_display_configs;
+  ctx->device.getDisplayAttributes = hwc_get_display_attributes;
+  ctx->device.getActiveConfig = hwc_get_active_config;
+  ctx->device.setActiveConfig = hwc_set_active_config;
+  ctx->device.setCursorPositionAsync = NULL;
+
+  *dev = &ctx->device.common;
+  ctx.release();
+
+  return 0;
+}
+}
+
+static struct hw_module_methods_t hwc1_module_methods = {
+    .open = android::hwc_device_open};
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag = HARDWARE_MODULE_TAG,
+        .version_major = 1,
+        .version_minor = 0,
+        .id = HWC_HARDWARE_MODULE_ID,
+        .name = "IA-Hardware-Composer",
+        .author = "The Android Open Source Project",
+        .methods = &hwc1_module_methods,
+        .dso = NULL,
+        .reserved = {0},
+    }};
index 680ef33..b2767ef 100644 (file)
@@ -159,11 +159,12 @@ bool DrmDisplay::GetDisplayAttribute(uint32_t config /*config*/,
 }
 
 bool DrmDisplay::GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) {
-  *num_configs = modes_.size();
+  size_t size = modes_.size();
+  *num_configs = size;
   if (!configs)
     return true;
 
-  for (uint32_t i = 0; i < *num_configs; i++)
+  for (uint32_t i = 0; i < size; i++)
     configs[i] = i;
 
   return true;