OSDN Git Service

drm_hwcomposer: Mark tests as vendor, fix build
[android-x86/external-drm_hwcomposer.git] / virtualcompositorworker.cpp
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 <log/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   Unlock();
93   Signal();
94 }
95
96 void VirtualCompositorWorker::Routine() {
97   int wait_ret = 0;
98
99   Lock();
100   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   }
109   Unlock();
110
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
121 int VirtualCompositorWorker::CreateNextTimelineFence() {
122   ++timeline_;
123   return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
124 }
125
126 int 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
138 void 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) {
148       ALOGE("Failed to wait for outbuf acquire %d/%d", outbuf_acquire_fence,
149             ret);
150       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) {
159         ALOGE("Failed to wait for layer acquire %d/%d", layer_acquire_fence,
160               ret);
161         return;
162       }
163       composition->layer_acquire_fences[i].Close();
164     }
165   }
166   FinishComposition(composition->release_timeline);
167 }
168 }