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 LOG_TAG "hwc-virtual-compositor-worker"
     18 
     19 #include "virtualcompositorworker.h"
     20 #include "worker.h"
     21 
     22 #include <errno.h>
     23 #include <stdlib.h>
     24 
     25 #include <cutils/log.h>
     26 #include <hardware/hardware.h>
     27 #include <hardware/hwcomposer.h>
     28 #include <sched.h>
     29 #include <sw_sync.h>
     30 #include <sync/sync.h>
     31 
     32 namespace android {
     33 
     34 static const int kMaxQueueDepth = 3;
     35 static const int kAcquireWaitTimeoutMs = 3000;
     36 
     37 VirtualCompositorWorker::VirtualCompositorWorker()
     38     : Worker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY),
     39       timeline_fd_(-1),
     40       timeline_(0),
     41       timeline_current_(0) {
     42 }
     43 
     44 VirtualCompositorWorker::~VirtualCompositorWorker() {
     45   if (timeline_fd_ >= 0) {
     46     FinishComposition(timeline_);
     47     close(timeline_fd_);
     48     timeline_fd_ = -1;
     49   }
     50 }
     51 
     52 int VirtualCompositorWorker::Init() {
     53   int ret = sw_sync_timeline_create();
     54   if (ret < 0) {
     55     ALOGE("Failed to create sw sync timeline %d", ret);
     56     return ret;
     57   }
     58   timeline_fd_ = ret;
     59   return InitWorker();
     60 }
     61 
     62 void VirtualCompositorWorker::QueueComposite(hwc_display_contents_1_t *dc) {
     63   std::unique_ptr<VirtualComposition> composition(new VirtualComposition);
     64 
     65   composition->outbuf_acquire_fence.Set(dc->outbufAcquireFenceFd);
     66   dc->outbufAcquireFenceFd = -1;
     67   if (dc->retireFenceFd >= 0)
     68     close(dc->retireFenceFd);
     69   dc->retireFenceFd = CreateNextTimelineFence();
     70 
     71   for (size_t i = 0; i < dc->numHwLayers; ++i) {
     72     hwc_layer_1_t *layer = &dc->hwLayers[i];
     73     if (layer->flags & HWC_SKIP_LAYER)
     74       continue;
     75     composition->layer_acquire_fences.emplace_back(layer->acquireFenceFd);
     76     layer->acquireFenceFd = -1;
     77     if (layer->releaseFenceFd >= 0)
     78       close(layer->releaseFenceFd);
     79     layer->releaseFenceFd = CreateNextTimelineFence();
     80   }
     81 
     82   composition->release_timeline = timeline_;
     83 
     84   Lock();
     85   while (composite_queue_.size() >= kMaxQueueDepth) {
     86     Unlock();
     87     sched_yield();
     88     Lock();
     89   }
     90 
     91   composite_queue_.push(std::move(composition));
     92   SignalLocked();
     93   Unlock();
     94 }
     95 
     96 void VirtualCompositorWorker::Routine() {
     97   int ret = Lock();
     98   if (ret) {
     99     ALOGE("Failed to lock worker, %d", ret);
    100     return;
    101   }
    102 
    103   int wait_ret = 0;
    104   if (composite_queue_.empty()) {
    105     wait_ret = WaitForSignalOrExitLocked();
    106   }
    107 
    108   std::unique_ptr<VirtualComposition> composition;
    109   if (!composite_queue_.empty()) {
    110     composition = std::move(composite_queue_.front());
    111     composite_queue_.pop();
    112   }
    113 
    114   ret = Unlock();
    115   if (ret) {
    116     ALOGE("Failed to unlock worker, %d", ret);
    117     return;
    118   }
    119 
    120   if (wait_ret == -EINTR) {
    121     return;
    122   } else if (wait_ret) {
    123     ALOGE("Failed to wait for signal, %d", wait_ret);
    124     return;
    125   }
    126 
    127   Compose(std::move(composition));
    128 }
    129 
    130 int VirtualCompositorWorker::CreateNextTimelineFence() {
    131   ++timeline_;
    132   return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
    133 }
    134 
    135 int VirtualCompositorWorker::FinishComposition(int point) {
    136   int timeline_increase = point - timeline_current_;
    137   if (timeline_increase <= 0)
    138     return 0;
    139   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
    140   if (ret)
    141     ALOGE("Failed to increment sync timeline %d", ret);
    142   else
    143     timeline_current_ = point;
    144   return ret;
    145 }
    146 
    147 void VirtualCompositorWorker::Compose(
    148     std::unique_ptr<VirtualComposition> composition) {
    149   if (!composition.get())
    150     return;
    151 
    152   int ret;
    153   int outbuf_acquire_fence = composition->outbuf_acquire_fence.get();
    154   if (outbuf_acquire_fence >= 0) {
    155     ret = sync_wait(outbuf_acquire_fence, kAcquireWaitTimeoutMs);
    156     if (ret) {
    157       ALOGE("Failed to wait for outbuf acquire %d/%d", outbuf_acquire_fence,
    158             ret);
    159       return;
    160     }
    161     composition->outbuf_acquire_fence.Close();
    162   }
    163   for (size_t i = 0; i < composition->layer_acquire_fences.size(); ++i) {
    164     int layer_acquire_fence = composition->layer_acquire_fences[i].get();
    165     if (layer_acquire_fence >= 0) {
    166       ret = sync_wait(layer_acquire_fence, kAcquireWaitTimeoutMs);
    167       if (ret) {
    168         ALOGE("Failed to wait for layer acquire %d/%d", layer_acquire_fence,
    169               ret);
    170         return;
    171       }
    172       composition->layer_acquire_fences[i].Close();
    173     }
    174   }
    175   FinishComposition(composition->release_timeline);
    176 }
    177 }
    178