Home | History | Annotate | Download | only in drm_hwcomposer
      1 /*
      2  * Copyright (C) 2015-2016 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 
     21 #include <cutils/log.h>
     22 #include <sw_sync.h>
     23 #include <sync/sync.h>
     24 
     25 namespace android {
     26 
     27 static const int kMaxQueueDepth = 3;
     28 static const int kAcquireWaitTimeoutMs = 3000;
     29 
     30 VirtualCompositorWorker::VirtualCompositorWorker()
     31     : QueueWorker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY),
     32       timeline_fd_(-1),
     33       timeline_(0),
     34       timeline_current_(0) {
     35 }
     36 
     37 VirtualCompositorWorker::~VirtualCompositorWorker() {
     38   if (timeline_fd_ >= 0) {
     39     FinishComposition(timeline_);
     40     close(timeline_fd_);
     41     timeline_fd_ = -1;
     42   }
     43 }
     44 
     45 int VirtualCompositorWorker::Init() {
     46   int ret = sw_sync_timeline_create();
     47   if (ret < 0) {
     48     ALOGE("Failed to create sw sync timeline %d", ret);
     49     return ret;
     50   }
     51   timeline_fd_ = ret;
     52 
     53   set_max_queue_size(kMaxQueueDepth);
     54   return InitWorker();
     55 }
     56 
     57 void VirtualCompositorWorker::QueueComposite(hwc_display_contents_1_t *dc) {
     58   std::unique_ptr<VirtualComposition> composition(new VirtualComposition);
     59 
     60   composition->outbuf_acquire_fence.Set(dc->outbufAcquireFenceFd);
     61   dc->outbufAcquireFenceFd = -1;
     62   if (dc->retireFenceFd >= 0)
     63     close(dc->retireFenceFd);
     64   dc->retireFenceFd = CreateNextTimelineFence();
     65 
     66   for (size_t i = 0; i < dc->numHwLayers; ++i) {
     67     hwc_layer_1_t *layer = &dc->hwLayers[i];
     68     if (layer->flags & HWC_SKIP_LAYER)
     69       continue;
     70     composition->layer_acquire_fences.emplace_back(layer->acquireFenceFd);
     71     layer->acquireFenceFd = -1;
     72     if (layer->releaseFenceFd >= 0)
     73       close(layer->releaseFenceFd);
     74     layer->releaseFenceFd = CreateNextTimelineFence();
     75   }
     76 
     77   composition->release_timeline = timeline_;
     78 
     79   QueueWork(std::move(composition));
     80 }
     81 
     82 int VirtualCompositorWorker::CreateNextTimelineFence() {
     83   ++timeline_;
     84   return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
     85 }
     86 
     87 int VirtualCompositorWorker::FinishComposition(int point) {
     88   int timeline_increase = point - timeline_current_;
     89   if (timeline_increase <= 0)
     90     return 0;
     91   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
     92   if (ret)
     93     ALOGE("Failed to increment sync timeline %d", ret);
     94   else
     95     timeline_current_ = point;
     96   return ret;
     97 }
     98 
     99 void VirtualCompositorWorker::ProcessWork(
    100     std::unique_ptr<VirtualComposition> composition) {
    101   if (!composition.get())
    102     return;
    103 
    104   int ret;
    105   int outbuf_acquire_fence = composition->outbuf_acquire_fence.get();
    106   if (outbuf_acquire_fence >= 0) {
    107     ret = sync_wait(outbuf_acquire_fence, kAcquireWaitTimeoutMs);
    108     if (ret) {
    109       ALOGE("Failed to wait for outbuf acquire %d/%d", outbuf_acquire_fence,
    110             ret);
    111       return;
    112     }
    113     composition->outbuf_acquire_fence.Close();
    114   }
    115   for (size_t i = 0; i < composition->layer_acquire_fences.size(); ++i) {
    116     int layer_acquire_fence = composition->layer_acquire_fences[i].get();
    117     if (layer_acquire_fence >= 0) {
    118       ret = sync_wait(layer_acquire_fence, kAcquireWaitTimeoutMs);
    119       if (ret) {
    120         ALOGE("Failed to wait for layer acquire %d/%d", layer_acquire_fence,
    121               ret);
    122         return;
    123       }
    124       composition->layer_acquire_fences[i].Close();
    125     }
    126   }
    127   FinishComposition(composition->release_timeline);
    128 }
    129 }
    130