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