2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "hwc-virtual-compositor-worker"
19 #include "virtualcompositorworker.h"
25 #include <cutils/log.h>
26 #include <hardware/hardware.h>
27 #include <hardware/hwcomposer.h>
30 #include <sync/sync.h>
34 static const int kMaxQueueDepth = 3;
35 static const int kAcquireWaitTimeoutMs = 50;
37 VirtualCompositorWorker::VirtualCompositorWorker()
38 : Worker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY)
41 , timeline_current_(0) {
44 VirtualCompositorWorker::~VirtualCompositorWorker() {
45 if (timeline_fd_ >= 0) {
46 FinishComposition(timeline_);
52 int VirtualCompositorWorker::Init() {
53 int ret = sw_sync_timeline_create();
55 ALOGE("Failed to create sw sync timeline %d", ret);
62 void VirtualCompositorWorker::QueueComposite(hwc_display_contents_1_t *dc) {
63 std::unique_ptr<VirtualComposition> composition(new VirtualComposition);
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();
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)
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();
82 composition->release_timeline = timeline_;
85 while (composite_queue_.size() >= kMaxQueueDepth) {
91 composite_queue_.push(std::move(composition));
96 void VirtualCompositorWorker::Routine() {
99 ALOGE("Failed to lock worker, %d", ret);
104 if (composite_queue_.empty()) {
105 wait_ret = WaitForSignalOrExitLocked();
108 std::unique_ptr<VirtualComposition> composition;
109 if (!composite_queue_.empty()) {
110 composition = std::move(composite_queue_.front());
111 composite_queue_.pop();
116 ALOGE("Failed to unlock worker, %d", ret);
120 if (wait_ret == -EINTR) {
122 } else if (wait_ret) {
123 ALOGE("Failed to wait for signal, %d", wait_ret);
127 Compose(std::move(composition));
130 int VirtualCompositorWorker::CreateNextTimelineFence() {
132 return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
135 int VirtualCompositorWorker::FinishComposition(int point) {
136 int timeline_increase = point - timeline_current_;
137 if (timeline_increase <= 0)
139 int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
141 ALOGE("Failed to increment sync timeline %d", ret);
143 timeline_current_ = point;
147 void VirtualCompositorWorker::Compose(
148 std::unique_ptr<VirtualComposition> composition) {
149 if (!composition.get())
153 int outbuf_acquire_fence = composition->outbuf_acquire_fence.get();
154 if (outbuf_acquire_fence >= 0) {
155 ret = sync_wait(outbuf_acquire_fence, kAcquireWaitTimeoutMs);
157 ALOGE("Failed to wait for acquire %d/%d", outbuf_acquire_fence, ret);
160 composition->outbuf_acquire_fence.Close();
162 for (size_t i = 0; i < composition->layer_acquire_fences.size(); ++i) {
163 int layer_acquire_fence = composition->layer_acquire_fences[i].get();
164 if (layer_acquire_fence >= 0) {
165 ret = sync_wait(layer_acquire_fence, kAcquireWaitTimeoutMs);
167 ALOGE("Failed to wait for acquire %d/%d", layer_acquire_fence, ret);
170 composition->layer_acquire_fences[i].Close();
173 FinishComposition(composition->release_timeline);