Home | History | Annotate | Download | only in dri
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/ozone/platform/dri/dri_util.h"
      6 
      7 #include <errno.h>
      8 #include <stdint.h>
      9 #include <stdlib.h>
     10 #include <sys/mman.h>
     11 #include <xf86drm.h>
     12 #include <xf86drmMode.h>
     13 
     14 namespace ui {
     15 
     16 namespace {
     17 
     18 bool IsCrtcInUse(uint32_t crtc,
     19                  const ScopedVector<HardwareDisplayControllerInfo>& displays) {
     20   for (size_t i = 0; i < displays.size(); ++i) {
     21     if (crtc == displays[i]->crtc()->crtc_id)
     22       return true;
     23   }
     24 
     25   return false;
     26 }
     27 
     28 uint32_t GetCrtc(int fd,
     29                  drmModeConnector* connector,
     30                  drmModeRes* resources,
     31                  const ScopedVector<HardwareDisplayControllerInfo>& displays) {
     32   // If the connector already has an encoder try to re-use.
     33   if (connector->encoder_id) {
     34     ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoder_id));
     35     if (encoder && encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays))
     36       return encoder->crtc_id;
     37   }
     38 
     39   // Try to find an encoder for the connector.
     40   for (int i = 0; i < connector->count_encoders; ++i) {
     41     ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoders[i]));
     42     if (!encoder)
     43       continue;
     44 
     45     for (int j = 0; j < resources->count_crtcs; ++j) {
     46       // Check if the encoder is compatible with this CRTC
     47       if (!(encoder->possible_crtcs & (1 << j)) ||
     48           IsCrtcInUse(resources->crtcs[j], displays))
     49         continue;
     50 
     51       return resources->crtcs[j];
     52     }
     53   }
     54 
     55   return 0;
     56 }
     57 
     58 }  // namespace
     59 
     60 HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
     61     ScopedDrmConnectorPtr connector,
     62     ScopedDrmCrtcPtr crtc)
     63     : connector_(connector.Pass()),
     64       crtc_(crtc.Pass()) {}
     65 
     66 HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() {}
     67 
     68 ScopedVector<HardwareDisplayControllerInfo>
     69 GetAvailableDisplayControllerInfos(int fd) {
     70   ScopedDrmResourcesPtr resources(drmModeGetResources(fd));
     71   DCHECK(resources) << "Failed to get DRM resources";
     72   ScopedVector<HardwareDisplayControllerInfo> displays;
     73 
     74   for (int i = 0; i < resources->count_connectors; ++i) {
     75     ScopedDrmConnectorPtr connector(drmModeGetConnector(
     76         fd, resources->connectors[i]));
     77 
     78     if (!connector || connector->connection != DRM_MODE_CONNECTED ||
     79         connector->count_modes == 0)
     80       continue;
     81 
     82     uint32_t crtc_id = GetCrtc(fd, connector.get(), resources.get(), displays);
     83     if (!crtc_id)
     84       continue;
     85 
     86     ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
     87     displays.push_back(new HardwareDisplayControllerInfo(connector.Pass(),
     88                                                          crtc.Pass()));
     89   }
     90 
     91   return displays.Pass();
     92 }
     93 
     94 bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) {
     95   return lhs.clock == rhs.clock &&
     96          lhs.hdisplay == rhs.hdisplay &&
     97          lhs.vdisplay == rhs.vdisplay &&
     98          lhs.vrefresh == rhs.vrefresh &&
     99          lhs.hsync_start == rhs.hsync_start &&
    100          lhs.hsync_end == rhs.hsync_end &&
    101          lhs.htotal == rhs.htotal &&
    102          lhs.hskew == rhs.hskew &&
    103          lhs.vsync_start == rhs.vsync_start &&
    104          lhs.vsync_end == rhs.vsync_end &&
    105          lhs.vtotal == rhs.vtotal &&
    106          lhs.vscan == rhs.vscan &&
    107          lhs.flags == rhs.flags &&
    108          strcmp(lhs.name, rhs.name) == 0;
    109 }
    110 
    111 bool MapDumbBuffer(int fd,
    112                    uint32_t handle,
    113                    uint32_t size,
    114                    void** pixels) {
    115   struct drm_mode_map_dumb map_request;
    116   memset(&map_request, 0, sizeof(map_request));
    117   map_request.handle = handle;
    118   if (drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map_request)) {
    119     VLOG(2) << "Cannot prepare dumb buffer for mapping (" << errno << ") "
    120             << strerror(errno);
    121     return false;
    122   }
    123 
    124   *pixels = mmap(0,
    125                  size,
    126                  PROT_READ | PROT_WRITE,
    127                  MAP_SHARED,
    128                  fd,
    129                  map_request.offset);
    130   if (*pixels == MAP_FAILED) {
    131     VLOG(2) << "Cannot mmap dumb buffer (" << errno << ") " << strerror(errno);
    132     return false;
    133   }
    134 
    135   return true;
    136 }
    137 
    138 }  // namespace ui
    139