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