2 // Copyright (c) 2017 Intel Corporation
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 #include "compositorthread.h"
21 #include "nativegpuresource.h"
22 #include "overlaylayer.h"
24 #include "resourcemanager.h"
25 #include "framebuffermanager.h"
26 #include "displayplanemanager.h"
27 #include "nativesurface.h"
29 #include <nativebufferhandler.h>
31 namespace hwcomposer {
33 CompositorThread::CompositorThread() : HWCThread(-8, "CompositorThread") {
34 if (!cevent_.Initialize())
37 fd_chandler_.AddFd(cevent_.get_fd());
40 CompositorThread::~CompositorThread() {
43 void CompositorThread::Initialize(ResourceManager *resource_manager,
46 if (!gpu_resource_handler_)
47 gpu_resource_handler_.reset(CreateNativeGpuResourceHandler());
49 resource_manager_ = resource_manager;
53 ETRACE("Failed to initalize CompositorThread. %s", PRINTERROR());
57 void CompositorThread::SetExplicitSyncSupport(bool disable_explicit_sync) {
58 disable_explicit_sync_ = disable_explicit_sync;
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());
71 tasks_ |= kRefreshRawPixelData;
74 if (!pixel_data_.empty()) {
79 void CompositorThread::EnsurePixelDataUpdated() {
80 pixel_data_lock_.lock();
81 pixel_data_lock_.unlock();
84 void CompositorThread::FreeResources() {
86 tasks_ |= kReleaseResources;
91 void CompositorThread::Wait() {
92 if (fd_chandler_.Poll(-1) <= 0) {
93 ETRACE("Poll Failed in DisplayManager %s", PRINTERROR());
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.
104 bool CompositorThread::Draw(std::vector<DrawState> &states,
105 std::vector<DrawState> &media_states,
106 const std::vector<OverlayLayer> &layers) {
107 states_.swap(states);
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());
120 if (!media_states.empty()) {
121 media_states_.swap(media_states);
122 tasks_ |= kRenderMedia;
125 // We start of assuming that the draw calls
127 draw_succeeded_ = true;
128 tasks_lock_.unlock();
131 return draw_succeeded_;
134 void CompositorThread::ExitThread() {
136 std::vector<DrawState>().swap(states_);
137 std::vector<OverlayBuffer *>().swap(buffers_);
140 void CompositorThread::HandleExit() {
141 HandleReleaseRequest();
142 gl_renderer_.reset(nullptr);
143 gpu_resource_handler_.reset(nullptr);
146 void CompositorThread::HandleRoutine() {
148 if (tasks_ & kRender3D) {
149 Handle3DDrawRequest();
153 if (tasks_ & kRenderMedia) {
154 HandleMediaDrawRequest();
158 if (tasks_ & kReleaseResources) {
159 HandleReleaseRequest();
162 if (tasks_ & kRefreshRawPixelData) {
163 HandleRawPixelUpdate();
171 void CompositorThread::HandleReleaseRequest() {
172 ScopedSpinLock lock(tasks_lock_);
173 tasks_ &= ~kReleaseResources;
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();
182 FrameBufferManager *pFBManager = FrameBufferManager::GetInstance(gpu_fd_);
184 if (purged_size != 0) {
185 if (has_gpu_resource) {
187 gpu_resource_handler_->ReleaseGPUResources(purged_gl_resources);
190 const NativeBufferHandler *handler =
191 resource_manager_->GetNativeBufferHandler();
193 for (size_t i = 0; i < purged_size; i++) {
194 const ResourceHandle &handle = purged_gl_resources.at(i);
195 bool fd_created = false;
200 pFBManager->RemoveFB(handle.drm_fd_,
201 handler->CanReleaseGemHandles(handle.handle_))) {
202 ETRACE("Failed to remove fb %s", PRINTERROR());
205 if (!handle.handle_) {
209 handler->ReleaseBuffer(handle.handle_, !fd_created);
210 handler->DestroyHandle(handle.handle_);
214 purged_size = purged_media_resources.size();
216 if (purged_size != 0) {
217 EnsureMediaRenderer();
218 media_renderer_->DestroyMediaResources(purged_media_resources);
220 const NativeBufferHandler *handler =
221 resource_manager_->GetNativeBufferHandler();
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());
231 if (!handle.handle_) {
235 handler->ReleaseBuffer(handle.handle_);
236 handler->DestroyHandle(handle.handle_);
241 void CompositorThread::HandleRawPixelUpdate() {
243 tasks_ &= ~kRefreshRawPixelData;
244 tasks_lock_.unlock();
246 std::vector<OverlayBuffer *> texture_uploads;
247 for (auto &buffer : pixel_data_) {
248 if (buffer->NeedsTextureUpload()) {
249 texture_uploads.emplace_back(buffer);
251 buffer->RefreshPixelData();
255 if (!texture_uploads.empty()) {
257 gpu_resource_handler_->HandleTextureUploads(texture_uploads);
260 pixel_data_lock_.unlock();
263 void CompositorThread::Handle3DDrawRequest() {
265 tasks_ &= ~kRender3D;
266 tasks_lock_.unlock();
270 draw_succeeded_ = false;
274 gl_renderer_->SetExplicitSyncSupport(disable_explicit_sync_);
276 if (!gpu_resource_handler_->PrepareResources(buffers_)) {
278 "Failed to prepare GPU resources for compositing the frame, "
281 draw_succeeded_ = false;
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_;
292 for (RenderState::LayerState &temp : layer_state) {
294 gpu_resource_handler_->GetResourceHandle(temp.layer_index_);
298 const std::vector<int32_t> &fences = draw_state.acquire_fences_;
299 for (int32_t fence : fences) {
300 gl_renderer_->InsertFence(fence);
303 std::vector<int32_t>().swap(draw_state.acquire_fences_);
305 if (!gl_renderer_->Draw(draw_state.states_, draw_state.surface_)) {
310 draw_succeeded_ = false;
314 if (draw_state.destroy_surface_) {
315 if (draw_succeeded_) {
316 draw_state.retire_fence_ =
317 draw_state.surface_->GetLayer()->ReleaseAcquireFence();
320 delete draw_state.surface_;
324 if (disable_explicit_sync_)
325 gl_renderer_->InsertFence(-1);
328 void CompositorThread::HandleMediaDrawRequest() {
330 tasks_ &= ~kRenderMedia;
331 tasks_lock_.unlock();
333 EnsureMediaRenderer();
334 if (!media_renderer_) {
335 draw_succeeded_ = false;
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_)) {
344 "Failed to render the frame by VA, "
347 draw_succeeded_ = false;
353 void CompositorThread::Ensure3DRenderer() {
355 gl_renderer_.reset(Create3DRenderer());
356 if (!gl_renderer_->Init()) {
357 ETRACE("Failed to initialize OpenGL compositor %s", PRINTERROR());
358 gl_renderer_.reset(nullptr);
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);
373 } // namespace hwcomposer