• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
VirtualCompositorWorker()30 VirtualCompositorWorker::VirtualCompositorWorker()
31     : QueueWorker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY),
32       timeline_fd_(-1),
33       timeline_(0),
34       timeline_current_(0) {
35 }
36 
~VirtualCompositorWorker()37 VirtualCompositorWorker::~VirtualCompositorWorker() {
38   if (timeline_fd_ >= 0) {
39     FinishComposition(timeline_);
40     close(timeline_fd_);
41     timeline_fd_ = -1;
42   }
43 }
44 
Init()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 
QueueComposite(hwc_display_contents_1_t * dc)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 
CreateNextTimelineFence()82 int VirtualCompositorWorker::CreateNextTimelineFence() {
83   ++timeline_;
84   return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
85 }
86 
FinishComposition(int point)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 
ProcessWork(std::unique_ptr<VirtualComposition> composition)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