Home | History | Annotate | Download | only in drm_hwcomposer
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
     18 #define LOG_TAG "hwcomposer-drm"
     19 
     20 #include "drm_hwcomposer.h"
     21 #include "drmresources.h"
     22 #include "gl_compositor.h"
     23 #include "importer.h"
     24 #include "vsyncworker.h"
     25 
     26 #include <errno.h>
     27 #include <fcntl.h>
     28 #include <list>
     29 #include <map>
     30 #include <pthread.h>
     31 #include <stdlib.h>
     32 #include <sys/param.h>
     33 #include <sys/resource.h>
     34 #include <xf86drm.h>
     35 #include <xf86drmMode.h>
     36 
     37 #include <cutils/log.h>
     38 #include <cutils/properties.h>
     39 #include <hardware/hardware.h>
     40 #include <hardware/hwcomposer.h>
     41 #include <sw_sync.h>
     42 #include <sync/sync.h>
     43 #include <ui/GraphicBuffer.h>
     44 #include <ui/PixelFormat.h>
     45 #include <utils/Trace.h>
     46 
     47 #define UM_PER_INCH 25400
     48 #define HWC_FB_BUFFERS 3
     49 
     50 namespace android {
     51 
     52 struct hwc_drm_display_framebuffer {
     53   hwc_drm_display_framebuffer() : release_fence_fd_(-1) {
     54   }
     55 
     56   ~hwc_drm_display_framebuffer() {
     57     if (release_fence_fd() >= 0)
     58       close(release_fence_fd());
     59   }
     60 
     61   bool is_valid() {
     62     return buffer_ != NULL;
     63   }
     64 
     65   sp<GraphicBuffer> buffer() {
     66     return buffer_;
     67   }
     68 
     69   int release_fence_fd() {
     70     return release_fence_fd_;
     71   }
     72 
     73   void set_release_fence_fd(int fd) {
     74     if (release_fence_fd_ >= 0)
     75       close(release_fence_fd_);
     76     release_fence_fd_ = fd;
     77   }
     78 
     79   bool Allocate(uint32_t w, uint32_t h) {
     80     if (is_valid()) {
     81       if (buffer_->getWidth() == w && buffer_->getHeight() == h)
     82         return true;
     83 
     84       if (release_fence_fd_ >= 0) {
     85         if (sync_wait(release_fence_fd_, -1) != 0) {
     86           return false;
     87         }
     88       }
     89       Clear();
     90     }
     91     buffer_ = new GraphicBuffer(w, h, android::PIXEL_FORMAT_RGBA_8888,
     92                                 GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER |
     93                                     GRALLOC_USAGE_HW_COMPOSER);
     94     release_fence_fd_ = -1;
     95     return is_valid();
     96   }
     97 
     98   void Clear() {
     99     if (!is_valid())
    100       return;
    101 
    102     if (release_fence_fd_ >= 0) {
    103       close(release_fence_fd_);
    104       release_fence_fd_ = -1;
    105     }
    106 
    107     buffer_.clear();
    108   }
    109 
    110   int WaitReleased(int timeout_milliseconds) {
    111     if (!is_valid())
    112       return 0;
    113     if (release_fence_fd_ < 0)
    114       return 0;
    115 
    116     int ret = sync_wait(release_fence_fd_, timeout_milliseconds);
    117     return ret;
    118   }
    119 
    120  private:
    121   sp<GraphicBuffer> buffer_;
    122   int release_fence_fd_;
    123 };
    124 
    125 
    126 typedef struct hwc_drm_display {
    127   struct hwc_context_t *ctx;
    128   int display;
    129 
    130   std::vector<uint32_t> config_ids;
    131 
    132   VSyncWorker vsync_worker;
    133 
    134   hwc_drm_display_framebuffer fb_chain[HWC_FB_BUFFERS];
    135   int fb_idx;
    136 } hwc_drm_display_t;
    137 
    138 struct hwc_context_t {
    139   // map of display:hwc_drm_display_t
    140   typedef std::map<int, hwc_drm_display_t> DisplayMap;
    141   typedef DisplayMap::iterator DisplayMapIter;
    142 
    143   hwc_context_t() : procs(NULL), importer(NULL) {
    144   }
    145 
    146   ~hwc_context_t() {
    147     delete importer;
    148   }
    149 
    150   hwc_composer_device_1_t device;
    151   hwc_procs_t const *procs;
    152 
    153   DisplayMap displays;
    154   DrmResources drm;
    155   Importer *importer;
    156   GLCompositor pre_compositor;
    157 };
    158 
    159 static void hwc_dump(struct hwc_composer_device_1* dev, char *buff,
    160                      int buff_len) {
    161   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    162   std::ostringstream out;
    163 
    164   ctx->drm.compositor()->Dump(&out);
    165   std::string out_str = out.str();
    166   strncpy(buff, out_str.c_str(), std::min((size_t)buff_len, out_str.length()));
    167 }
    168 
    169 static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
    170                        hwc_display_contents_1_t **display_contents) {
    171   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    172   for (int i = 0; i < (int)num_displays; ++i) {
    173     if (!display_contents[i])
    174       continue;
    175 
    176     DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
    177     if (!crtc) {
    178       ALOGE("No crtc for display %d", i);
    179       return -ENODEV;
    180     }
    181 
    182     int num_layers = display_contents[i]->numHwLayers;
    183     for (int j = 0; j < num_layers; j++) {
    184       hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
    185 
    186       if (layer->compositionType == HWC_FRAMEBUFFER)
    187         layer->compositionType = HWC_OVERLAY;
    188     }
    189   }
    190 
    191   return 0;
    192 }
    193 
    194 static void hwc_set_cleanup(size_t num_displays,
    195                             hwc_display_contents_1_t **display_contents,
    196                             Composition *composition) {
    197   for (int i = 0; i < (int)num_displays; ++i) {
    198     if (!display_contents[i])
    199       continue;
    200 
    201     hwc_display_contents_1_t *dc = display_contents[i];
    202     for (size_t j = 0; j < dc->numHwLayers; ++j) {
    203       hwc_layer_1_t *layer = &dc->hwLayers[j];
    204       if (layer->acquireFenceFd >= 0) {
    205         close(layer->acquireFenceFd);
    206         layer->acquireFenceFd = -1;
    207       }
    208     }
    209     if (dc->outbufAcquireFenceFd >= 0) {
    210       close(dc->outbufAcquireFenceFd);
    211       dc->outbufAcquireFenceFd = -1;
    212     }
    213   }
    214 
    215   delete composition;
    216 }
    217 
    218 static int hwc_add_layer(int display, hwc_context_t *ctx, hwc_layer_1_t *layer,
    219                          Composition *composition) {
    220   hwc_drm_bo_t bo;
    221   int ret = ctx->importer->ImportBuffer(layer->handle, &bo);
    222   if (ret) {
    223     ALOGE("Failed to import handle to bo %d", ret);
    224     return ret;
    225   }
    226 
    227   ret = composition->AddLayer(display, layer, &bo);
    228   if (!ret)
    229     return 0;
    230 
    231   int destroy_ret = ctx->importer->ReleaseBuffer(&bo);
    232   if (destroy_ret)
    233     ALOGE("Failed to destroy buffer %d", destroy_ret);
    234 
    235   return ret;
    236 }
    237 
    238 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
    239                    hwc_display_contents_1_t **display_contents) {
    240   ATRACE_CALL();
    241   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    242   Composition *composition =
    243       ctx->drm.compositor()->CreateComposition(ctx->importer);
    244   if (!composition) {
    245     ALOGE("Drm composition init failed");
    246     hwc_set_cleanup(num_displays, display_contents, NULL);
    247     return -EINVAL;
    248   }
    249 
    250   int ret;
    251   for (int i = 0; i < (int)num_displays; ++i) {
    252     if (!display_contents[i])
    253       continue;
    254 
    255     hwc_display_contents_1_t *dc = display_contents[i];
    256     int j;
    257     unsigned num_layers = 0;
    258     unsigned num_dc_layers = dc->numHwLayers;
    259     for (j = 0; j < (int)num_dc_layers; ++j) {
    260       hwc_layer_1_t *layer = &dc->hwLayers[j];
    261       if (layer->flags & HWC_SKIP_LAYER)
    262         continue;
    263       if (layer->compositionType == HWC_OVERLAY)
    264         num_layers++;
    265     }
    266 
    267     unsigned num_planes = composition->GetRemainingLayers(i, num_layers);
    268     bool use_pre_compositor = false;
    269 
    270     if (num_layers > num_planes) {
    271       use_pre_compositor = true;
    272       // Reserve one of the planes for the result of the pre compositor.
    273       num_planes--;
    274     }
    275 
    276     for (j = 0; num_planes && j < (int)num_dc_layers; ++j) {
    277       hwc_layer_1_t *layer = &dc->hwLayers[j];
    278       if (layer->flags & HWC_SKIP_LAYER)
    279         continue;
    280       if (layer->compositionType != HWC_OVERLAY)
    281         continue;
    282 
    283       ret = hwc_add_layer(i, ctx, layer, composition);
    284       if (ret) {
    285         ALOGE("Add layer failed %d", ret);
    286         hwc_set_cleanup(num_displays, display_contents, composition);
    287         return ret;
    288       }
    289       --num_planes;
    290     }
    291 
    292     int last_comp_layer = j;
    293 
    294     if (use_pre_compositor) {
    295       hwc_drm_display_t *hd = &ctx->displays[i];
    296       struct hwc_drm_display_framebuffer *fb = &hd->fb_chain[hd->fb_idx];
    297       ret = fb->WaitReleased(-1);
    298       if (ret) {
    299         ALOGE("Failed to wait for framebuffer %d", ret);
    300         hwc_set_cleanup(num_displays, display_contents, composition);
    301         return ret;
    302       }
    303 
    304       DrmConnector *connector = ctx->drm.GetConnectorForDisplay(i);
    305       if (!connector) {
    306         ALOGE("No connector for display %d", i);
    307         hwc_set_cleanup(num_displays, display_contents, composition);
    308         return -ENODEV;
    309       }
    310 
    311       const DrmMode &mode = connector->active_mode();
    312       if (!fb->Allocate(mode.h_display(), mode.v_display())) {
    313         ALOGE("Failed to allocate framebuffer with size %dx%d",
    314               mode.h_display(), mode.v_display());
    315         hwc_set_cleanup(num_displays, display_contents, composition);
    316         return -EINVAL;
    317       }
    318 
    319       sp<GraphicBuffer> fb_buffer = fb->buffer();
    320       if (fb_buffer == NULL) {
    321         ALOGE("Framebuffer is NULL");
    322         hwc_set_cleanup(num_displays, display_contents, composition);
    323         return -EINVAL;
    324       }
    325 
    326       Targeting *targeting = ctx->pre_compositor.targeting();
    327       if (targeting == NULL) {
    328         ALOGE("Pre-compositor does not support targeting");
    329         hwc_set_cleanup(num_displays, display_contents, composition);
    330         return -EINVAL;
    331       }
    332 
    333       int target = targeting->CreateTarget(fb_buffer);
    334       targeting->SetTarget(target);
    335 
    336       Composition *pre_composition = ctx->pre_compositor.CreateComposition(ctx->importer);
    337       if (pre_composition == NULL) {
    338         ALOGE("Failed to create pre-composition");
    339         targeting->ForgetTarget(target);
    340         hwc_set_cleanup(num_displays, display_contents, composition);
    341         return -EINVAL;
    342       }
    343 
    344       for (j = last_comp_layer; j < (int)num_dc_layers; ++j) {
    345         hwc_layer_1_t *layer = &dc->hwLayers[j];
    346         if (layer->flags & HWC_SKIP_LAYER)
    347           continue;
    348         if (layer->compositionType != HWC_OVERLAY)
    349           continue;
    350         ret = hwc_add_layer(i, ctx, layer, pre_composition);
    351         if (ret) {
    352           ALOGE("Add layer failed %d", ret);
    353           delete pre_composition;
    354           targeting->ForgetTarget(target);
    355           hwc_set_cleanup(num_displays, display_contents, composition);
    356           return ret;
    357         }
    358       }
    359 
    360       ret = ctx->pre_compositor.QueueComposition(pre_composition);
    361       pre_composition = NULL;
    362 
    363       targeting->ForgetTarget(target);
    364       if (ret < 0 && ret != -EALREADY) {
    365         ALOGE("Pre-composition failed %d", ret);
    366         hwc_set_cleanup(num_displays, display_contents, composition);
    367         return ret;
    368       }
    369 
    370       for (j = last_comp_layer; j < (int)num_dc_layers; ++j) {
    371         hwc_layer_1_t *layer = &dc->hwLayers[j];
    372         if (layer->flags & HWC_SKIP_LAYER)
    373           continue;
    374         if (layer->compositionType != HWC_OVERLAY)
    375           continue;
    376         layer->acquireFenceFd = -1;
    377       }
    378 
    379       hwc_layer_1_t composite_layer;
    380       hwc_rect_t visible_rect;
    381       memset(&composite_layer, 0, sizeof(composite_layer));
    382       memset(&visible_rect, 0, sizeof(visible_rect));
    383 
    384       composite_layer.compositionType = HWC_OVERLAY;
    385       composite_layer.handle = fb_buffer->getNativeBuffer()->handle;
    386       composite_layer.sourceCropf.right = composite_layer.displayFrame.right =
    387           visible_rect.right = fb_buffer->getWidth();
    388       composite_layer.sourceCropf.bottom = composite_layer.displayFrame.bottom =
    389           visible_rect.bottom = fb_buffer->getHeight();
    390       composite_layer.visibleRegionScreen.numRects = 1;
    391       composite_layer.visibleRegionScreen.rects = &visible_rect;
    392       composite_layer.acquireFenceFd = ret == -EALREADY ? -1 : ret;
    393       // A known invalid fd in case AddLayer does not modify this field.
    394       composite_layer.releaseFenceFd = -1;
    395       composite_layer.planeAlpha = 0xff;
    396 
    397       ret = hwc_add_layer(i, ctx, &composite_layer, composition);
    398       if (ret) {
    399         ALOGE("Add layer failed %d", ret);
    400         hwc_set_cleanup(num_displays, display_contents, composition);
    401         return ret;
    402       }
    403 
    404       fb->set_release_fence_fd(composite_layer.releaseFenceFd);
    405       hd->fb_idx = (hd->fb_idx + 1) % HWC_FB_BUFFERS;
    406     }
    407   }
    408 
    409   ret = ctx->drm.compositor()->QueueComposition(composition);
    410   composition = NULL;
    411   if (ret) {
    412     ALOGE("Failed to queue the composition");
    413     hwc_set_cleanup(num_displays, display_contents, NULL);
    414     return ret;
    415   }
    416   hwc_set_cleanup(num_displays, display_contents, NULL);
    417   return ret;
    418 }
    419 
    420 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
    421                              int event, int enabled) {
    422   if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
    423     return -EINVAL;
    424 
    425   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    426   hwc_drm_display_t *hd = &ctx->displays[display];
    427   return hd->vsync_worker.VSyncControl(enabled);
    428 }
    429 
    430 static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
    431                               int mode) {
    432   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    433 
    434   uint64_t dpmsValue = 0;
    435   switch (mode) {
    436     case HWC_POWER_MODE_OFF:
    437       dpmsValue = DRM_MODE_DPMS_OFF;
    438       break;
    439 
    440     /* We can't support dozing right now, so go full on */
    441     case HWC_POWER_MODE_DOZE:
    442     case HWC_POWER_MODE_DOZE_SUSPEND:
    443     case HWC_POWER_MODE_NORMAL:
    444       dpmsValue = DRM_MODE_DPMS_ON;
    445       break;
    446   };
    447   return ctx->drm.SetDpmsMode(display, dpmsValue);
    448 }
    449 
    450 static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
    451                      int *value) {
    452   switch (what) {
    453     case HWC_BACKGROUND_LAYER_SUPPORTED:
    454       *value = 0; /* TODO: We should do this */
    455       break;
    456     case HWC_VSYNC_PERIOD:
    457       ALOGW("Query for deprecated vsync value, returning 60Hz");
    458       *value = 1000 * 1000 * 1000 / 60;
    459       break;
    460     case HWC_DISPLAY_TYPES_SUPPORTED:
    461       *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
    462       break;
    463   }
    464   return 0;
    465 }
    466 
    467 static void hwc_register_procs(struct hwc_composer_device_1 *dev,
    468                                hwc_procs_t const *procs) {
    469   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    470 
    471   ctx->procs = procs;
    472 
    473   for (hwc_context_t::DisplayMapIter iter = ctx->displays.begin();
    474        iter != ctx->displays.end(); ++iter) {
    475     iter->second.vsync_worker.SetProcs(procs);
    476   }
    477 }
    478 
    479 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
    480                                    int display, uint32_t *configs,
    481                                    size_t *num_configs) {
    482   if (!*num_configs)
    483     return 0;
    484 
    485   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    486   hwc_drm_display_t *hd = &ctx->displays[display];
    487   hd->config_ids.clear();
    488 
    489   DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
    490   if (!connector) {
    491     ALOGE("Failed to get connector for display %d", display);
    492     return -ENODEV;
    493   }
    494 
    495   int ret = connector->UpdateModes();
    496   if (ret) {
    497     ALOGE("Failed to update display modes %d", ret);
    498     return ret;
    499   }
    500 
    501   for (DrmConnector::ModeIter iter = connector->begin_modes();
    502        iter != connector->end_modes(); ++iter) {
    503     size_t idx = hd->config_ids.size();
    504     if (idx == *num_configs)
    505       break;
    506     hd->config_ids.push_back(iter->id());
    507     configs[idx] = iter->id();
    508   }
    509   *num_configs = hd->config_ids.size();
    510   return *num_configs == 0 ? -1 : 0;
    511 }
    512 
    513 static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
    514                                       int display, uint32_t config,
    515                                       const uint32_t *attributes,
    516                                       int32_t *values) {
    517   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    518   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
    519   if (!c) {
    520     ALOGE("Failed to get DrmConnector for display %d", display);
    521     return -ENODEV;
    522   }
    523   DrmMode mode;
    524   for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
    525        ++iter) {
    526     if (iter->id() == config) {
    527       mode = *iter;
    528       break;
    529     }
    530   }
    531   if (mode.id() == 0) {
    532     ALOGE("Failed to find active mode for display %d", display);
    533     return -ENOENT;
    534   }
    535 
    536   uint32_t mm_width = c->mm_width();
    537   uint32_t mm_height = c->mm_height();
    538   for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
    539     switch (attributes[i]) {
    540       case HWC_DISPLAY_VSYNC_PERIOD:
    541         values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
    542         break;
    543       case HWC_DISPLAY_WIDTH:
    544         values[i] = mode.h_display();
    545         break;
    546       case HWC_DISPLAY_HEIGHT:
    547         values[i] = mode.v_display();
    548         break;
    549       case HWC_DISPLAY_DPI_X:
    550         /* Dots per 1000 inches */
    551         values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
    552         break;
    553       case HWC_DISPLAY_DPI_Y:
    554         /* Dots per 1000 inches */
    555         values[i] =
    556             mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
    557         break;
    558     }
    559   }
    560   return 0;
    561 }
    562 
    563 static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
    564                                  int display) {
    565   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    566   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
    567   if (!c) {
    568     ALOGE("Failed to get DrmConnector for display %d", display);
    569     return -ENODEV;
    570   }
    571 
    572   DrmMode mode = c->active_mode();
    573   hwc_drm_display_t *hd = &ctx->displays[display];
    574   for (size_t i = 0; i < hd->config_ids.size(); ++i) {
    575     if (hd->config_ids[i] == mode.id())
    576       return i;
    577   }
    578   return -1;
    579 }
    580 
    581 static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
    582                                  int index) {
    583   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
    584   hwc_drm_display_t *hd = &ctx->displays[display];
    585   if (index >= (int)hd->config_ids.size()) {
    586     ALOGE("Invalid config index %d passed in", index);
    587     return -EINVAL;
    588   }
    589 
    590   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
    591   if (!c) {
    592     ALOGE("Failed to get connector for display %d", display);
    593     return -ENODEV;
    594   }
    595   DrmMode mode;
    596   for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
    597        ++iter) {
    598     if (iter->id() == hd->config_ids[index]) {
    599       mode = *iter;
    600       break;
    601     }
    602   }
    603   if (mode.id() != hd->config_ids[index]) {
    604     ALOGE("Could not find active mode for %d/%d", index, hd->config_ids[index]);
    605     return -ENOENT;
    606   }
    607   int ret = ctx->drm.SetDisplayActiveMode(display, mode);
    608   if (ret) {
    609     ALOGE("Failed to set active config %d", ret);
    610     return ret;
    611   }
    612   return ret;
    613 }
    614 
    615 static int hwc_device_close(struct hw_device_t *dev) {
    616   struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
    617   delete ctx;
    618   return 0;
    619 }
    620 
    621 /*
    622  * TODO: This function sets the active config to the first one in the list. This
    623  * should be fixed such that it selects the preferred mode for the display, or
    624  * some other, saner, method of choosing the config.
    625  */
    626 static int hwc_set_initial_config(hwc_drm_display_t *hd) {
    627   uint32_t config;
    628   size_t num_configs = 1;
    629   int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
    630                                     &num_configs);
    631   if (ret || !num_configs)
    632     return 0;
    633 
    634   ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
    635   if (ret) {
    636     ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
    637     return ret;
    638   }
    639 
    640   return ret;
    641 }
    642 
    643 static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
    644   hwc_drm_display_t *hd = &ctx->displays[display];
    645   hd->ctx = ctx;
    646   hd->display = display;
    647   hd->fb_idx = 0;
    648 
    649   int ret = hwc_set_initial_config(hd);
    650   if (ret) {
    651     ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
    652     return ret;
    653   }
    654 
    655   ret = hd->vsync_worker.Init(&ctx->drm, display);
    656   if (ret) {
    657     ALOGE("Failed to create event worker for display %d %d\n", display, ret);
    658     return ret;
    659   }
    660 
    661   return 0;
    662 }
    663 
    664 static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
    665   int ret;
    666   for (DrmResources::ConnectorIter c = ctx->drm.begin_connectors();
    667        c != ctx->drm.end_connectors(); ++c) {
    668     ret = hwc_initialize_display(ctx, (*c)->display());
    669     if (ret) {
    670       ALOGE("Failed to initialize display %d", (*c)->display());
    671       return ret;
    672     }
    673   }
    674 
    675   return 0;
    676 }
    677 
    678 static int hwc_device_open(const struct hw_module_t *module, const char *name,
    679                            struct hw_device_t **dev) {
    680   if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
    681     ALOGE("Invalid module name- %s", name);
    682     return -EINVAL;
    683   }
    684 
    685   struct hwc_context_t *ctx = new hwc_context_t();
    686   if (!ctx) {
    687     ALOGE("Failed to allocate hwc context");
    688     return -ENOMEM;
    689   }
    690 
    691   int ret = ctx->drm.Init();
    692   if (ret) {
    693     ALOGE("Can't initialize Drm object %d", ret);
    694     delete ctx;
    695     return ret;
    696   }
    697 
    698   ret = ctx->pre_compositor.Init();
    699   if (ret) {
    700     ALOGE("Can't initialize OpenGL Compositor object %d", ret);
    701     delete ctx;
    702     return ret;
    703   }
    704 
    705   ctx->importer = Importer::CreateInstance(&ctx->drm);
    706   if (!ctx->importer) {
    707     ALOGE("Failed to create importer instance");
    708     delete ctx;
    709     return ret;
    710   }
    711 
    712   ret = hwc_enumerate_displays(ctx);
    713   if (ret) {
    714     ALOGE("Failed to enumerate displays: %s", strerror(ret));
    715     delete ctx;
    716     return ret;
    717   }
    718 
    719   ctx->device.common.tag = HARDWARE_DEVICE_TAG;
    720   ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
    721   ctx->device.common.module = const_cast<hw_module_t *>(module);
    722   ctx->device.common.close = hwc_device_close;
    723 
    724   ctx->device.dump = hwc_dump;
    725   ctx->device.prepare = hwc_prepare;
    726   ctx->device.set = hwc_set;
    727   ctx->device.eventControl = hwc_event_control;
    728   ctx->device.setPowerMode = hwc_set_power_mode;
    729   ctx->device.query = hwc_query;
    730   ctx->device.registerProcs = hwc_register_procs;
    731   ctx->device.getDisplayConfigs = hwc_get_display_configs;
    732   ctx->device.getDisplayAttributes = hwc_get_display_attributes;
    733   ctx->device.getActiveConfig = hwc_get_active_config;
    734   ctx->device.setActiveConfig = hwc_set_active_config;
    735   ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
    736 
    737   *dev = &ctx->device.common;
    738 
    739   return 0;
    740 }
    741 }
    742 
    743 static struct hw_module_methods_t hwc_module_methods = {
    744   open : android::hwc_device_open
    745 };
    746 
    747 hwc_module_t HAL_MODULE_INFO_SYM = {
    748   common : {
    749     tag : HARDWARE_MODULE_TAG,
    750     version_major : 1,
    751     version_minor : 0,
    752     id : HWC_HARDWARE_MODULE_ID,
    753     name : "DRM hwcomposer module",
    754     author : "The Android Open Source Project",
    755     methods : &hwc_module_methods,
    756     dso : NULL,
    757     reserved : {0},
    758   }
    759 };
    760