OSDN Git Service

fcb483bc5933fc5aa83d3da338ed1f60054926ed
[android-x86/external-IA-Hardware-Composer.git] / common / compositor / compositorthread.cpp
1 /*
2 // Copyright (c) 2017 Intel Corporation
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 #include "compositorthread.h"
18
19 #include "hwcutils.h"
20 #include "hwctrace.h"
21 #include "nativegpuresource.h"
22 #include "overlaylayer.h"
23 #include "renderer.h"
24 #include "resourcemanager.h"
25 #include "framebuffermanager.h"
26 #include "displayplanemanager.h"
27 #include "nativesurface.h"
28
29 #include <nativebufferhandler.h>
30
31 namespace hwcomposer {
32
33 CompositorThread::CompositorThread() : HWCThread(-8, "CompositorThread") {
34   if (!cevent_.Initialize())
35     return;
36
37   fd_chandler_.AddFd(cevent_.get_fd());
38 }
39
40 CompositorThread::~CompositorThread() {
41 }
42
43 void CompositorThread::Initialize(ResourceManager *resource_manager,
44                                   uint32_t gpu_fd) {
45   tasks_lock_.lock();
46   if (!gpu_resource_handler_)
47     gpu_resource_handler_.reset(CreateNativeGpuResourceHandler());
48
49   resource_manager_ = resource_manager;
50   gpu_fd_ = gpu_fd;
51   tasks_lock_.unlock();
52   if (!InitWorker()) {
53     ETRACE("Failed to initalize CompositorThread. %s", PRINTERROR());
54   }
55 }
56
57 void CompositorThread::SetExplicitSyncSupport(bool disable_explicit_sync) {
58   disable_explicit_sync_ = disable_explicit_sync;
59 }
60
61 void CompositorThread::UpdateLayerPixelData(std::vector<OverlayLayer> &layers) {
62   if (!layers.empty()) {
63     pixel_data_lock_.lock();
64     std::vector<OverlayBuffer *>().swap(pixel_data_);
65     for (auto &layer : layers) {
66       if (layer.RawPixelDataChanged()) {
67         pixel_data_.emplace_back(layer.GetBuffer());
68       }
69     }
70
71     tasks_ |= kRefreshRawPixelData;
72   }
73
74   if (!pixel_data_.empty()) {
75     Resume();
76   }
77 }
78
79 void CompositorThread::EnsurePixelDataUpdated() {
80   pixel_data_lock_.lock();
81   pixel_data_lock_.unlock();
82 }
83
84 void CompositorThread::FreeResources() {
85   tasks_lock_.lock();
86   tasks_ |= kReleaseResources;
87   tasks_lock_.unlock();
88   Resume();
89 }
90
91 void CompositorThread::Wait() {
92   if (fd_chandler_.Poll(-1) <= 0) {
93     ETRACE("Poll Failed in DisplayManager %s", PRINTERROR());
94     return;
95   }
96
97   if (fd_chandler_.IsReady(cevent_.get_fd())) {
98     // If eventfd_ is ready, we need to wait on it (using read()) to clean
99     // the flag that says it is ready.
100     cevent_.Wait();
101   }
102 }
103
104 bool CompositorThread::Draw(std::vector<DrawState> &states,
105                             std::vector<DrawState> &media_states,
106                             const std::vector<OverlayLayer> &layers) {
107   states_.swap(states);
108   tasks_lock_.lock();
109
110   if (!states_.empty()) {
111     std::vector<OverlayBuffer *>().swap(buffers_);
112     buffers_.reserve(layers.size());
113     for (auto &layer : layers) {
114       buffers_.emplace_back(layer.GetBuffer());
115     }
116
117     tasks_ |= kRender3D;
118   }
119
120   if (!media_states.empty()) {
121     media_states_.swap(media_states);
122     tasks_ |= kRenderMedia;
123   }
124
125   // We start of assuming that the draw calls
126   // succeed.
127   draw_succeeded_ = true;
128   tasks_lock_.unlock();
129   Resume();
130   Wait();
131   return draw_succeeded_;
132 }
133
134 void CompositorThread::ExitThread() {
135   HWCThread::Exit();
136   std::vector<DrawState>().swap(states_);
137   std::vector<OverlayBuffer *>().swap(buffers_);
138 }
139
140 void CompositorThread::HandleExit() {
141   HandleReleaseRequest();
142   gl_renderer_.reset(nullptr);
143   gpu_resource_handler_.reset(nullptr);
144 }
145
146 void CompositorThread::HandleRoutine() {
147   bool signal = false;
148   if (tasks_ & kRender3D) {
149     Handle3DDrawRequest();
150     signal = true;
151   }
152
153   if (tasks_ & kRenderMedia) {
154     HandleMediaDrawRequest();
155     signal = true;
156   }
157
158   if (tasks_ & kReleaseResources) {
159     HandleReleaseRequest();
160   }
161
162   if (tasks_ & kRefreshRawPixelData) {
163     HandleRawPixelUpdate();
164   }
165
166   if (signal) {
167     cevent_.Signal();
168   }
169 }
170
171 void CompositorThread::HandleReleaseRequest() {
172   ScopedSpinLock lock(tasks_lock_);
173   tasks_ &= ~kReleaseResources;
174
175   std::vector<ResourceHandle> purged_gl_resources;
176   std::vector<MediaResourceHandle> purged_media_resources;
177   bool has_gpu_resource = false;
178   resource_manager_->GetPurgedResources(
179       purged_gl_resources, purged_media_resources, &has_gpu_resource);
180   size_t purged_size = purged_gl_resources.size();
181
182   FrameBufferManager *pFBManager = FrameBufferManager::GetInstance(gpu_fd_);
183
184   if (purged_size != 0) {
185     if (has_gpu_resource) {
186       Ensure3DRenderer();
187       gpu_resource_handler_->ReleaseGPUResources(purged_gl_resources);
188     }
189
190     const NativeBufferHandler *handler =
191         resource_manager_->GetNativeBufferHandler();
192
193     for (size_t i = 0; i < purged_size; i++) {
194       const ResourceHandle &handle = purged_gl_resources.at(i);
195       bool fd_created = false;
196       if (handle.drm_fd_)
197         fd_created = true;
198
199       if (fd_created &&
200           pFBManager->RemoveFB(handle.drm_fd_,
201                                handler->CanReleaseGemHandles(handle.handle_))) {
202         ETRACE("Failed to remove fb %s", PRINTERROR());
203       }
204
205       if (!handle.handle_) {
206         continue;
207       }
208
209       handler->ReleaseBuffer(handle.handle_, !fd_created);
210       handler->DestroyHandle(handle.handle_);
211     }
212   }
213
214   purged_size = purged_media_resources.size();
215
216   if (purged_size != 0) {
217     EnsureMediaRenderer();
218     media_renderer_->DestroyMediaResources(purged_media_resources);
219
220     const NativeBufferHandler *handler =
221         resource_manager_->GetNativeBufferHandler();
222
223     for (size_t i = 0; i < purged_size; i++) {
224       const MediaResourceHandle &handle = purged_media_resources.at(i);
225       if (handle.drm_fd_ &&
226           pFBManager->RemoveFB(handle.drm_fd_,
227                                handler->CanReleaseGemHandles(handle.handle_))) {
228         ETRACE("Failed to remove fb %s", PRINTERROR());
229       }
230
231       if (!handle.handle_) {
232         continue;
233       }
234
235       handler->ReleaseBuffer(handle.handle_);
236       handler->DestroyHandle(handle.handle_);
237     }
238   }
239 }
240
241 void CompositorThread::HandleRawPixelUpdate() {
242   tasks_lock_.lock();
243   tasks_ &= ~kRefreshRawPixelData;
244   tasks_lock_.unlock();
245
246   std::vector<OverlayBuffer *> texture_uploads;
247   for (auto &buffer : pixel_data_) {
248     if (buffer->NeedsTextureUpload()) {
249       texture_uploads.emplace_back(buffer);
250     } else {
251       buffer->RefreshPixelData();
252     }
253   }
254
255   if (!texture_uploads.empty()) {
256     Ensure3DRenderer();
257     gpu_resource_handler_->HandleTextureUploads(texture_uploads);
258   }
259
260   pixel_data_lock_.unlock();
261 }
262
263 void CompositorThread::Handle3DDrawRequest() {
264   tasks_lock_.lock();
265   tasks_ &= ~kRender3D;
266   tasks_lock_.unlock();
267
268   Ensure3DRenderer();
269   if (!gl_renderer_) {
270     draw_succeeded_ = false;
271     return;
272   }
273
274   gl_renderer_->SetExplicitSyncSupport(disable_explicit_sync_);
275
276   if (!gpu_resource_handler_->PrepareResources(buffers_)) {
277     ETRACE(
278         "Failed to prepare GPU resources for compositing the frame, "
279         "error: %s",
280         PRINTERROR());
281     draw_succeeded_ = false;
282     return;
283   }
284
285   size_t size = states_.size();
286   for (size_t i = 0; i < size; i++) {
287     DrawState &draw_state = states_.at(i);
288     for (RenderState &render_state : draw_state.states_) {
289       std::vector<RenderState::LayerState> &layer_state =
290           render_state.layer_state_;
291
292       for (RenderState::LayerState &temp : layer_state) {
293         temp.handle_ =
294             gpu_resource_handler_->GetResourceHandle(temp.layer_index_);
295       }
296     }
297
298     const std::vector<int32_t> &fences = draw_state.acquire_fences_;
299     for (int32_t fence : fences) {
300       gl_renderer_->InsertFence(fence);
301     }
302
303     std::vector<int32_t>().swap(draw_state.acquire_fences_);
304
305     if (!gl_renderer_->Draw(draw_state.states_, draw_state.surface_)) {
306       ETRACE(
307           "Failed to Draw: "
308           "error: %s",
309           PRINTERROR());
310       draw_succeeded_ = false;
311       break;
312     }
313
314     if (draw_state.destroy_surface_) {
315       if (draw_succeeded_) {
316         draw_state.retire_fence_ =
317             draw_state.surface_->GetLayer()->ReleaseAcquireFence();
318       }
319
320       delete draw_state.surface_;
321     }
322   }
323
324   if (disable_explicit_sync_)
325     gl_renderer_->InsertFence(-1);
326 }
327
328 void CompositorThread::HandleMediaDrawRequest() {
329   tasks_lock_.lock();
330   tasks_ &= ~kRenderMedia;
331   tasks_lock_.unlock();
332
333   EnsureMediaRenderer();
334   if (!media_renderer_) {
335     draw_succeeded_ = false;
336     return;
337   }
338
339   size_t size = media_states_.size();
340   for (size_t i = 0; i < size; i++) {
341     DrawState &draw_state = media_states_[i];
342     if (!media_renderer_->Draw(draw_state.media_state_, draw_state.surface_)) {
343       ETRACE(
344           "Failed to render the frame by VA, "
345           "error: %s\n",
346           PRINTERROR());
347       draw_succeeded_ = false;
348       break;
349     }
350   }
351 }
352
353 void CompositorThread::Ensure3DRenderer() {
354   if (!gl_renderer_) {
355     gl_renderer_.reset(Create3DRenderer());
356     if (!gl_renderer_->Init()) {
357       ETRACE("Failed to initialize OpenGL compositor %s", PRINTERROR());
358       gl_renderer_.reset(nullptr);
359     }
360   }
361 }
362
363 void CompositorThread::EnsureMediaRenderer() {
364   if (!media_renderer_) {
365     media_renderer_.reset(CreateMediaRenderer());
366     if (!media_renderer_->Init(gpu_fd_)) {
367       ETRACE("Failed to initialize Media Renderer %s", PRINTERROR());
368       media_renderer_.reset(nullptr);
369     }
370   }
371 }
372
373 }  // namespace hwcomposer