C++程序  |  168行  |  5.17 KB

/*
 * 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.
 */

#define LOG_TAG "hwc-drm-composition"

#include "drmcomposition.h"
#include "drmcrtc.h"
#include "drmplane.h"
#include "drmresources.h"

#include <stdlib.h>

#include <cutils/log.h>
#include <cutils/properties.h>
#include <sw_sync.h>
#include <sync/sync.h>

namespace android {

DrmComposition::DrmComposition(DrmResources *drm, Importer *importer)
    : drm_(drm), importer_(importer) {
  char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
  property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1");
  bool use_overlay_planes = atoi(use_overlay_planes_prop);

  for (DrmResources::PlaneIter iter = drm_->begin_planes();
       iter != drm_->end_planes(); ++iter) {
    if ((*iter)->type() == DRM_PLANE_TYPE_PRIMARY)
      primary_planes_.push_back(*iter);
    else if (use_overlay_planes && (*iter)->type() == DRM_PLANE_TYPE_OVERLAY)
      overlay_planes_.push_back(*iter);
  }
}

int DrmComposition::Init(uint64_t frame_no) {
  for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
       iter != drm_->end_connectors(); ++iter) {
    int display = (*iter)->display();
    composition_map_[display].reset(new DrmDisplayComposition());
    if (!composition_map_[display]) {
      ALOGE("Failed to allocate new display composition\n");
      return -ENOMEM;
    }

    // If the display hasn't been modeset yet, this will be NULL
    DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);

    int ret = composition_map_[display]->Init(drm_, crtc, importer_, frame_no);
    if (ret) {
      ALOGE("Failed to init display composition for %d", display);
      return ret;
    }
  }
  return 0;
}

int DrmComposition::SetLayers(size_t num_displays,
                              DrmCompositionDisplayLayersMap *maps) {
  int ret = 0;
  for (size_t display_index = 0; display_index < num_displays;
       display_index++) {
    DrmCompositionDisplayLayersMap &map = maps[display_index];
    int display = map.display;

    if (!drm_->GetConnectorForDisplay(display)) {
      ALOGE("Invalid display given to SetLayers %d", display);
      continue;
    }

    ret = composition_map_[display]->SetLayers(
        map.layers.data(), map.layers.size(), map.geometry_changed);
    if (ret)
      return ret;
  }

  return 0;
}

int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) {
  return composition_map_[display]->SetDpmsMode(dpms_mode);
}

int DrmComposition::SetDisplayMode(int display, const DrmMode &display_mode) {
  return composition_map_[display]->SetDisplayMode(display_mode);
}

std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
    int display) {
  return std::move(composition_map_[display]);
}

int DrmComposition::Plan(std::map<int, DrmDisplayCompositor> &compositor_map) {
  int ret = 0;
  for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
       iter != drm_->end_connectors(); ++iter) {
    int display = (*iter)->display();
    DrmDisplayComposition *comp = GetDisplayComposition(display);
    ret = comp->Plan(compositor_map[display].squash_state(), &primary_planes_,
                     &overlay_planes_);
    if (ret) {
      ALOGE("Failed to plan composition for dislay %d", display);
      return ret;
    }
  }

  return 0;
}

int DrmComposition::DisableUnusedPlanes() {
  for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
       iter != drm_->end_connectors(); ++iter) {
    int display = (*iter)->display();
    DrmDisplayComposition *comp = GetDisplayComposition(display);

    /*
     * Leave empty compositions alone
     * TODO: re-visit this and potentially disable leftover planes after the
     *       active compositions have gobbled up all they can
     */
    if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY ||
        comp->type() == DRM_COMPOSITION_TYPE_MODESET)
      continue;

    DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
    if (!crtc) {
      ALOGE("Failed to find crtc for display %d", display);
      continue;
    }

    for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
         iter != primary_planes_.end(); ++iter) {
      if ((*iter)->GetCrtcSupported(*crtc)) {
        comp->AddPlaneDisable(*iter);
        primary_planes_.erase(iter);
        break;
      }
    }
    for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
         iter != overlay_planes_.end();) {
      if ((*iter)->GetCrtcSupported(*crtc)) {
        comp->AddPlaneDisable(*iter);
        iter = overlay_planes_.erase(iter);
      } else {
        iter++;
      }
    }
  }
  return 0;
}

DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) {
  return composition_map_[display].get();
}
}