blob: 639dc860a1b3be1a6416db68daa5cd18767703f5 [file] [log] [blame]
Haixia Shid21f5282015-10-05 14:35:09 -07001/*
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
32namespace android {
33
34static const int kMaxQueueDepth = 3;
Sean Paulfaca2092015-11-16 13:47:19 -050035static const int kAcquireWaitTimeoutMs = 3000;
Haixia Shid21f5282015-10-05 14:35:09 -070036
37VirtualCompositorWorker::VirtualCompositorWorker()
Haixia Shi479412c2015-10-27 10:40:48 -070038 : Worker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY),
39 timeline_fd_(-1),
40 timeline_(0),
41 timeline_current_(0) {
Haixia Shid21f5282015-10-05 14:35:09 -070042}
43
44VirtualCompositorWorker::~VirtualCompositorWorker() {
45 if (timeline_fd_ >= 0) {
46 FinishComposition(timeline_);
47 close(timeline_fd_);
48 timeline_fd_ = -1;
49 }
50}
51
52int 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
62void 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));
Haixia Shid21f5282015-10-05 14:35:09 -070092 Unlock();
Adrian Salidofa37f672017-02-16 10:29:46 -080093 Signal();
Haixia Shid21f5282015-10-05 14:35:09 -070094}
95
96void VirtualCompositorWorker::Routine() {
Haixia Shid21f5282015-10-05 14:35:09 -070097 int wait_ret = 0;
Adrian Salidofa37f672017-02-16 10:29:46 -080098
99 Lock();
Haixia Shid21f5282015-10-05 14:35:09 -0700100 if (composite_queue_.empty()) {
101 wait_ret = WaitForSignalOrExitLocked();
102 }
103
104 std::unique_ptr<VirtualComposition> composition;
105 if (!composite_queue_.empty()) {
106 composition = std::move(composite_queue_.front());
107 composite_queue_.pop();
108 }
Adrian Salidofa37f672017-02-16 10:29:46 -0800109 Unlock();
Haixia Shid21f5282015-10-05 14:35:09 -0700110
111 if (wait_ret == -EINTR) {
112 return;
113 } else if (wait_ret) {
114 ALOGE("Failed to wait for signal, %d", wait_ret);
115 return;
116 }
117
118 Compose(std::move(composition));
119}
120
121int VirtualCompositorWorker::CreateNextTimelineFence() {
122 ++timeline_;
123 return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
124}
125
126int VirtualCompositorWorker::FinishComposition(int point) {
127 int timeline_increase = point - timeline_current_;
128 if (timeline_increase <= 0)
129 return 0;
130 int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
131 if (ret)
132 ALOGE("Failed to increment sync timeline %d", ret);
133 else
134 timeline_current_ = point;
135 return ret;
136}
137
138void VirtualCompositorWorker::Compose(
139 std::unique_ptr<VirtualComposition> composition) {
140 if (!composition.get())
141 return;
142
143 int ret;
144 int outbuf_acquire_fence = composition->outbuf_acquire_fence.get();
145 if (outbuf_acquire_fence >= 0) {
146 ret = sync_wait(outbuf_acquire_fence, kAcquireWaitTimeoutMs);
147 if (ret) {
Sean Paulfaca2092015-11-16 13:47:19 -0500148 ALOGE("Failed to wait for outbuf acquire %d/%d", outbuf_acquire_fence,
149 ret);
Haixia Shid21f5282015-10-05 14:35:09 -0700150 return;
151 }
152 composition->outbuf_acquire_fence.Close();
153 }
154 for (size_t i = 0; i < composition->layer_acquire_fences.size(); ++i) {
155 int layer_acquire_fence = composition->layer_acquire_fences[i].get();
156 if (layer_acquire_fence >= 0) {
157 ret = sync_wait(layer_acquire_fence, kAcquireWaitTimeoutMs);
158 if (ret) {
Sean Paulfaca2092015-11-16 13:47:19 -0500159 ALOGE("Failed to wait for layer acquire %d/%d", layer_acquire_fence,
160 ret);
Haixia Shid21f5282015-10-05 14:35:09 -0700161 return;
162 }
163 composition->layer_acquire_fences[i].Close();
164 }
165 }
166 FinishComposition(composition->release_timeline);
167}
168}