From patchwork Wed Sep 27 11:58:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Foss X-Patchwork-Id: 9973869 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 51EE0602D6 for ; Wed, 27 Sep 2017 11:59:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 40CAF27BFF for ; Wed, 27 Sep 2017 11:59:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 354AF28DF0; Wed, 27 Sep 2017 11:59:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8140427BFF for ; Wed, 27 Sep 2017 11:59:10 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CA1396E708; Wed, 27 Sep 2017 11:59:04 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by gabe.freedesktop.org (Postfix) with ESMTPS id 704046E6F8 for ; Wed, 27 Sep 2017 11:59:01 +0000 (UTC) Received: from localhost.localdomain (unknown [IPv6:2a02:8109:9a3f:ee3b:c7ab:3df6:4b82:1a62]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: robertfoss) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id BB26926CE4F; Wed, 27 Sep 2017 12:58:59 +0100 (BST) From: Robert Foss To: dri-devel@lists.freedesktop.org, robh@kernel.org, salidoa@google.com, seanpaul@chromium.org, zachr@google.com Subject: [PATCH hwc v2 1/6] drm_hwcomposer: Remove threading Date: Wed, 27 Sep 2017 13:58:36 +0200 Message-Id: <20170927115841.29134-2-robert.foss@collabora.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170927115841.29134-1-robert.foss@collabora.com> References: <20170927115841.29134-1-robert.foss@collabora.com> Cc: Robert Foss X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sean Paul Since HWC2 doesn't require the use of threads to implement correct synchronization, remove some of these threads. Signed-off-by: Robert Foss Signed-off-by: Sean Paul --- Android.mk | 3 - drmcomposition.cpp | 166 ---------------------------------------- drmcomposition.h | 79 ------------------- drmcompositor.cpp | 106 -------------------------- drmcompositor.h | 56 -------------- drmcompositorworker.h | 41 ---------- drmdisplaycomposition.cpp | 1 + drmdisplaycomposition.h | 10 +++ drmdisplaycompositor.cpp | 189 ++++------------------------------------------ drmdisplaycompositor.h | 36 +-------- drmeventlistener.cpp | 3 + drmhwctwo.cpp | 6 +- drmresources.cpp | 54 +------------ drmresources.h | 5 -- glworker.cpp | 52 +++++++++++-- glworker.h | 10 +++ 16 files changed, 93 insertions(+), 724 deletions(-) delete mode 100644 drmcomposition.cpp delete mode 100644 drmcomposition.h delete mode 100644 drmcompositor.cpp delete mode 100644 drmcompositor.h delete mode 100644 drmcompositorworker.h diff --git a/Android.mk b/Android.mk index aa95b44..5d16c2f 100644 --- a/Android.mk +++ b/Android.mk @@ -57,9 +57,6 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := \ autolock.cpp \ drmresources.cpp \ - drmcomposition.cpp \ - drmcompositor.cpp \ - drmcompositorworker.cpp \ drmconnector.cpp \ drmcrtc.cpp \ drmdisplaycomposition.cpp \ diff --git a/drmcomposition.cpp b/drmcomposition.cpp deleted file mode 100644 index 1aaf920..0000000 --- a/drmcomposition.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "hwc-drm-composition" - -#include "drmcomposition.h" -#include "drmcrtc.h" -#include "drmplane.h" -#include "drmresources.h" -#include "platform.h" - -#include - -#include -#include -#include -#include - -namespace android { - -DrmComposition::DrmComposition(DrmResources *drm, Importer *importer, - Planner *planner) - : drm_(drm), importer_(importer), planner_(planner) { - char use_overlay_planes_prop[PROPERTY_VALUE_MAX]; - property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1"); - bool use_overlay_planes = atoi(use_overlay_planes_prop); - - for (auto &plane : drm->planes()) { - if (plane->type() == DRM_PLANE_TYPE_PRIMARY) - primary_planes_.push_back(plane.get()); - else if (use_overlay_planes && plane->type() == DRM_PLANE_TYPE_OVERLAY) - overlay_planes_.push_back(plane.get()); - } -} - -int DrmComposition::Init(uint64_t frame_no) { - for (auto &conn : drm_->connectors()) { - int display = conn->display(); - composition_map_[display].reset(new DrmDisplayComposition()); - if (!composition_map_[display]) { - ALOGE("Failed to allocate new display composition\n"); - return -ENOMEM; - } - - // If the display hasn't been modeset yet, this will be NULL - DrmCrtc *crtc = drm_->GetCrtcForDisplay(display); - - int ret = composition_map_[display]->Init(drm_, crtc, importer_, planner_, - frame_no); - if (ret) { - ALOGE("Failed to init display composition for %d", display); - return ret; - } - } - return 0; -} - -int DrmComposition::SetLayers(size_t num_displays, - DrmCompositionDisplayLayersMap *maps) { - int ret = 0; - for (size_t display_index = 0; display_index < num_displays; - display_index++) { - DrmCompositionDisplayLayersMap &map = maps[display_index]; - int display = map.display; - - if (!drm_->GetConnectorForDisplay(display)) { - ALOGE("Invalid display given to SetLayers %d", display); - continue; - } - - ret = composition_map_[display]->SetLayers( - map.layers.data(), map.layers.size(), map.geometry_changed); - if (ret) - return ret; - } - - return 0; -} - -int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) { - return composition_map_[display]->SetDpmsMode(dpms_mode); -} - -int DrmComposition::SetDisplayMode(int display, const DrmMode &display_mode) { - return composition_map_[display]->SetDisplayMode(display_mode); -} - -std::unique_ptr DrmComposition::TakeDisplayComposition( - int display) { - return std::move(composition_map_[display]); -} - -int DrmComposition::Plan(std::map &compositor_map) { - int ret = 0; - for (auto &conn : drm_->connectors()) { - int display = conn->display(); - DrmDisplayComposition *comp = GetDisplayComposition(display); - ret = comp->Plan(compositor_map[display].squash_state(), &primary_planes_, - &overlay_planes_); - if (ret) { - ALOGE("Failed to plan composition for dislay %d", display); - return ret; - } - } - - return 0; -} - -int DrmComposition::DisableUnusedPlanes() { - for (auto &conn : drm_->connectors()) { - int display = conn->display(); - DrmDisplayComposition *comp = GetDisplayComposition(display); - - /* - * Leave empty compositions alone - * TODO: re-visit this and potentially disable leftover planes after the - * active compositions have gobbled up all they can - */ - if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY || - comp->type() == DRM_COMPOSITION_TYPE_MODESET) - continue; - - DrmCrtc *crtc = drm_->GetCrtcForDisplay(display); - if (!crtc) { - ALOGE("Failed to find crtc for display %d", display); - continue; - } - - for (std::vector::iterator iter = primary_planes_.begin(); - iter != primary_planes_.end(); ++iter) { - if ((*iter)->GetCrtcSupported(*crtc)) { - comp->AddPlaneDisable(*iter); - primary_planes_.erase(iter); - break; - } - } - for (std::vector::iterator iter = overlay_planes_.begin(); - iter != overlay_planes_.end();) { - if ((*iter)->GetCrtcSupported(*crtc)) { - comp->AddPlaneDisable(*iter); - iter = overlay_planes_.erase(iter); - } else { - iter++; - } - } - } - return 0; -} - -DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) { - return composition_map_[display].get(); -} -} diff --git a/drmcomposition.h b/drmcomposition.h deleted file mode 100644 index eae8cde..0000000 --- a/drmcomposition.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_DRM_COMPOSITION_H_ -#define ANDROID_DRM_COMPOSITION_H_ - -#include "drmhwcomposer.h" -#include "drmdisplaycomposition.h" -#include "drmplane.h" -#include "platform.h" - -#include -#include - -#include -#include - -namespace android { - -class DrmDisplayCompositor; - -struct DrmCompositionDisplayLayersMap { - int display; - bool geometry_changed = true; - std::vector layers; - - DrmCompositionDisplayLayersMap() = default; - DrmCompositionDisplayLayersMap(DrmCompositionDisplayLayersMap &&rhs) = - default; -}; - -class DrmComposition { - public: - DrmComposition(DrmResources *drm, Importer *importer, Planner *planner); - - int Init(uint64_t frame_no); - - int SetLayers(size_t num_displays, DrmCompositionDisplayLayersMap *maps); - int SetDpmsMode(int display, uint32_t dpms_mode); - int SetDisplayMode(int display, const DrmMode &display_mode); - - std::unique_ptr TakeDisplayComposition(int display); - DrmDisplayComposition *GetDisplayComposition(int display); - - int Plan(std::map &compositor_map); - int DisableUnusedPlanes(); - - private: - DrmComposition(const DrmComposition &) = delete; - - DrmResources *drm_; - Importer *importer_; - Planner *planner_; - - std::vector primary_planes_; - std::vector overlay_planes_; - - /* - * This _must_ be read-only after it's passed to QueueComposition. Otherwise - * locking is required to maintain consistency across the compositor threads. - */ - std::map> composition_map_; -}; -} - -#endif // ANDROID_DRM_COMPOSITION_H_ diff --git a/drmcompositor.cpp b/drmcompositor.cpp deleted file mode 100644 index c1f3ed8..0000000 --- a/drmcompositor.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "hwc-drm-compositor" - -#include "drmcompositor.h" -#include "drmdisplaycompositor.h" -#include "drmresources.h" -#include "platform.h" - -#include -#include - -#include - -namespace android { - -DrmCompositor::DrmCompositor(DrmResources *drm) : drm_(drm), frame_no_(0) { -} - -DrmCompositor::~DrmCompositor() { -} - -int DrmCompositor::Init() { - for (auto &conn : drm_->connectors()) { - int display = conn->display(); - int ret = compositor_map_[display].Init(drm_, display); - if (ret) { - ALOGE("Failed to initialize display compositor for %d", display); - return ret; - } - } - planner_ = Planner::CreateInstance(drm_); - if (!planner_) { - ALOGE("Failed to create planner instance for composition"); - return -ENOMEM; - } - - return 0; -} - -std::unique_ptr DrmCompositor::CreateComposition( - Importer *importer) { - std::unique_ptr composition( - new DrmComposition(drm_, importer, planner_.get())); - int ret = composition->Init(++frame_no_); - if (ret) { - ALOGE("Failed to initialize drm composition %d", ret); - return nullptr; - } - return composition; -} - -int DrmCompositor::QueueComposition( - std::unique_ptr composition) { - int ret; - - ret = composition->Plan(compositor_map_); - if (ret) - return ret; - - ret = composition->DisableUnusedPlanes(); - if (ret) - return ret; - - for (auto &conn : drm_->connectors()) { - int display = conn->display(); - int ret = compositor_map_[display].QueueComposition( - composition->TakeDisplayComposition(display)); - if (ret) { - ALOGE("Failed to queue composition for display %d (%d)", display, ret); - return ret; - } - } - - return 0; -} - -int DrmCompositor::Composite() { - /* - * This shouldn't be called, we should be calling Composite() on the display - * compositors directly. - */ - ALOGE("Calling base drm compositor Composite() function"); - return -EINVAL; -} - -void DrmCompositor::Dump(std::ostringstream *out) const { - *out << "DrmCompositor stats:\n"; - for (auto &conn : drm_->connectors()) - compositor_map_[conn->display()].Dump(out); -} -} diff --git a/drmcompositor.h b/drmcompositor.h deleted file mode 100644 index 19271b5..0000000 --- a/drmcompositor.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_DRM_COMPOSITOR_H_ -#define ANDROID_DRM_COMPOSITOR_H_ - -#include "drmcomposition.h" -#include "drmdisplaycompositor.h" -#include "platform.h" - -#include -#include -#include - -namespace android { - -class DrmCompositor { - public: - DrmCompositor(DrmResources *drm); - ~DrmCompositor(); - - int Init(); - - std::unique_ptr CreateComposition(Importer *importer); - - int QueueComposition(std::unique_ptr composition); - int Composite(); - void Dump(std::ostringstream *out) const; - - private: - DrmCompositor(const DrmCompositor &) = delete; - - DrmResources *drm_; - std::unique_ptr planner_; - - uint64_t frame_no_; - - // mutable for Dump() propagation - mutable std::map compositor_map_; -}; -} - -#endif // ANDROID_DRM_COMPOSITOR_H_ diff --git a/drmcompositorworker.h b/drmcompositorworker.h deleted file mode 100644 index 731bc65..0000000 --- a/drmcompositorworker.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_DRM_COMPOSITOR_WORKER_H_ -#define ANDROID_DRM_COMPOSITOR_WORKER_H_ - -#include "worker.h" - -namespace android { - -class DrmDisplayCompositor; - -class DrmCompositorWorker : public Worker { - public: - DrmCompositorWorker(DrmDisplayCompositor *compositor); - ~DrmCompositorWorker() override; - - int Init(); - - protected: - void Routine() override; - - DrmDisplayCompositor *compositor_; - bool did_squash_all_ = false; -}; -} - -#endif diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp index 0f8084b..66e67a4 100644 --- a/drmdisplaycomposition.cpp +++ b/drmdisplaycomposition.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "hwc-drm-display-composition" #include "drmdisplaycomposition.h" +#include "drmdisplaycompositor.h" #include "drmcrtc.h" #include "drmplane.h" #include "drmresources.h" diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h index 13da19d..b165adc 100644 --- a/drmdisplaycomposition.h +++ b/drmdisplaycomposition.h @@ -42,6 +42,16 @@ enum DrmCompositionType { DRM_COMPOSITION_TYPE_MODESET, }; +struct DrmCompositionDisplayLayersMap { + int display; + bool geometry_changed = true; + std::vector layers; + + DrmCompositionDisplayLayersMap() = default; + DrmCompositionDisplayLayersMap(DrmCompositionDisplayLayersMap &&rhs) = + default; +}; + struct DrmCompositionRegion { DrmHwcRect frame; std::vector source_layers; diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp index a1baed1..bd670cf 100644 --- a/drmdisplaycompositor.cpp +++ b/drmdisplaycompositor.cpp @@ -37,8 +37,6 @@ #include "drmresources.h" #include "glworker.h" -#define DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH 2 - namespace android { void SquashState::Init(DrmHwcLayer *layers, size_t num_layers) { @@ -176,58 +174,9 @@ static bool UsesSquash(const std::vector &comp_planes) { }); } -DrmDisplayCompositor::FrameWorker::FrameWorker(DrmDisplayCompositor *compositor) - : Worker("frame-worker", HAL_PRIORITY_URGENT_DISPLAY), - compositor_(compositor) { -} - -DrmDisplayCompositor::FrameWorker::~FrameWorker() { -} - -int DrmDisplayCompositor::FrameWorker::Init() { - return InitWorker(); -} - -void DrmDisplayCompositor::FrameWorker::QueueFrame( - std::unique_ptr composition, int status) { - Lock(); - FrameState frame; - frame.composition = std::move(composition); - frame.status = status; - frame_queue_.push(std::move(frame)); - Unlock(); - Signal(); -} - -void DrmDisplayCompositor::FrameWorker::Routine() { - int wait_ret = 0; - - Lock(); - if (frame_queue_.empty()) { - wait_ret = WaitForSignalOrExitLocked(); - } - - FrameState frame; - if (!frame_queue_.empty()) { - frame = std::move(frame_queue_.front()); - frame_queue_.pop(); - } - Unlock(); - - if (wait_ret == -EINTR) { - return; - } else if (wait_ret) { - ALOGE("Failed to wait for signal, %d", wait_ret); - return; - } - compositor_->ApplyFrame(std::move(frame.composition), frame.status); -} - DrmDisplayCompositor::DrmDisplayCompositor() : drm_(NULL), display_(-1), - worker_(this), - frame_worker_(this), initialized_(false), active_(false), use_hw_overlays_(true), @@ -245,9 +194,6 @@ DrmDisplayCompositor::~DrmDisplayCompositor() { if (!initialized_) return; - worker_.Exit(); - frame_worker_.Exit(); - int ret = pthread_mutex_lock(&lock_); if (ret) ALOGE("Failed to acquire compositor lock %d", ret); @@ -257,10 +203,6 @@ DrmDisplayCompositor::~DrmDisplayCompositor() { if (mode_.old_blob_id) drm_->DestroyPropertyBlob(mode_.old_blob_id); - while (!composite_queue_.empty()) { - composite_queue_.front().reset(); - composite_queue_.pop(); - } active_composition_.reset(); ret = pthread_mutex_unlock(&lock_); @@ -279,18 +221,6 @@ int DrmDisplayCompositor::Init(DrmResources *drm, int display) { ALOGE("Failed to initialize drm compositor lock %d\n", ret); return ret; } - ret = worker_.Init(); - if (ret) { - pthread_mutex_destroy(&lock_); - ALOGE("Failed to initialize compositor worker %d\n", ret); - return ret; - } - ret = frame_worker_.Init(); - if (ret) { - pthread_mutex_destroy(&lock_); - ALOGE("Failed to initialize frame worker %d\n", ret); - return ret; - } initialized_ = true; return 0; @@ -301,55 +231,6 @@ std::unique_ptr DrmDisplayCompositor::CreateComposition() return std::unique_ptr(new DrmDisplayComposition()); } -int DrmDisplayCompositor::QueueComposition( - std::unique_ptr composition) { - switch (composition->type()) { - case DRM_COMPOSITION_TYPE_FRAME: - if (!active_) - return -ENODEV; - break; - case DRM_COMPOSITION_TYPE_DPMS: - /* - * Update the state as soon as we get it so we can start/stop queuing - * frames asap. - */ - active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON); - break; - case DRM_COMPOSITION_TYPE_MODESET: - break; - case DRM_COMPOSITION_TYPE_EMPTY: - return 0; - default: - ALOGE("Unknown composition type %d/%d", composition->type(), display_); - return -ENOENT; - } - - int ret = pthread_mutex_lock(&lock_); - if (ret) { - ALOGE("Failed to acquire compositor lock %d", ret); - return ret; - } - - // Block the queue if it gets too large. Otherwise, SurfaceFlinger will start - // to eat our buffer handles when we get about 1 second behind. - while (composite_queue_.size() >= DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH) { - pthread_mutex_unlock(&lock_); - sched_yield(); - pthread_mutex_lock(&lock_); - } - - composite_queue_.push(std::move(composition)); - - ret = pthread_mutex_unlock(&lock_); - if (ret) { - ALOGE("Failed to release compositor lock %d", ret); - return ret; - } - - worker_.Signal(); - return 0; -} - std::tuple DrmDisplayCompositor::GetActiveModeResolution() { DrmConnector *connector = drm_->GetConnectorForDisplay(display_); @@ -514,6 +395,15 @@ int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) { std::vector &pre_comp_regions = display_comp->pre_comp_regions(); + if (!pre_compositor_) { + pre_compositor_.reset(new GLWorkerCompositor()); + int ret = pre_compositor_->Init(); + if (ret) { + ALOGE("Failed to initialize OpenGL compositor %d", ret); + return ret; + } + } + int squash_layer_index = -1; if (squash_regions.size() > 0) { squash_framebuffer_index_ = (squash_framebuffer_index_ + 1) % 2; @@ -906,41 +796,9 @@ void DrmDisplayCompositor::ApplyFrame( ALOGE("Failed to release lock for active_composition swap"); } -int DrmDisplayCompositor::Composite() { - ATRACE_CALL(); - - if (!pre_compositor_) { - pre_compositor_.reset(new GLWorkerCompositor()); - int ret = pre_compositor_->Init(); - if (ret) { - ALOGE("Failed to initialize OpenGL compositor %d", ret); - return ret; - } - } - - int ret = pthread_mutex_lock(&lock_); - if (ret) { - ALOGE("Failed to acquire compositor lock %d", ret); - return ret; - } - if (composite_queue_.empty()) { - ret = pthread_mutex_unlock(&lock_); - if (ret) - ALOGE("Failed to release compositor lock %d", ret); - return ret; - } - - std::unique_ptr composition( - std::move(composite_queue_.front())); - - composite_queue_.pop(); - - ret = pthread_mutex_unlock(&lock_); - if (ret) { - ALOGE("Failed to release compositor lock %d", ret); - return ret; - } - +int DrmDisplayCompositor::ApplyComposition( + std::unique_ptr composition) { + int ret = 0; switch (composition->type()) { case DRM_COMPOSITION_TYPE_FRAME: ret = PrepareFrame(composition.get()); @@ -959,7 +817,7 @@ int DrmDisplayCompositor::Composite() { } // If use_hw_overlays_ is false, we can't use hardware to composite the - // frame. So squash all layers into a single composition and queue that + // frame. So squash all layers into a single composition and apply that // instead. if (!use_hw_overlays_) { std::unique_ptr squashed = CreateComposition(); @@ -975,9 +833,10 @@ int DrmDisplayCompositor::Composite() { return ret; } } - frame_worker_.QueueFrame(std::move(composition), ret); + ApplyFrame(std::move(composition), ret); break; case DRM_COMPOSITION_TYPE_DPMS: + active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON); ret = ApplyDpms(composition.get()); if (ret) ALOGE("Failed to apply dpms for display %d", display_); @@ -1001,24 +860,6 @@ int DrmDisplayCompositor::Composite() { return ret; } -bool DrmDisplayCompositor::HaveQueuedComposites() const { - int ret = pthread_mutex_lock(&lock_); - if (ret) { - ALOGE("Failed to acquire compositor lock %d", ret); - return false; - } - - bool empty_ret = !composite_queue_.empty(); - - ret = pthread_mutex_unlock(&lock_); - if (ret) { - ALOGE("Failed to release compositor lock %d", ret); - return false; - } - - return empty_ret; -} - int DrmDisplayCompositor::SquashAll() { AutoLock lock(&lock_, "compositor"); int ret = lock.Lock(); diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h index 9487cac..f1965fb 100644 --- a/drmdisplaycompositor.h +++ b/drmdisplaycompositor.h @@ -18,14 +18,12 @@ #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_ #include "drmhwcomposer.h" -#include "drmcomposition.h" -#include "drmcompositorworker.h" +#include "drmdisplaycomposition.h" #include "drmframebuffer.h" #include "separate_rects.h" #include #include -#include #include #include @@ -89,42 +87,18 @@ class DrmDisplayCompositor { int Init(DrmResources *drm, int display); std::unique_ptr CreateComposition() const; - int QueueComposition(std::unique_ptr composition); + int ApplyComposition(std::unique_ptr composition); int Composite(); int SquashAll(); void Dump(std::ostringstream *out) const; std::tuple GetActiveModeResolution(); - bool HaveQueuedComposites() const; - SquashState *squash_state() { return &squash_state_; } private: - struct FrameState { - std::unique_ptr composition; - int status = 0; - }; - - class FrameWorker : public Worker { - public: - FrameWorker(DrmDisplayCompositor *compositor); - ~FrameWorker() override; - - int Init(); - void QueueFrame(std::unique_ptr composition, - int status); - - protected: - void Routine() override; - - private: - DrmDisplayCompositor *compositor_; - std::queue frame_queue_; - }; - struct ModeState { bool needs_modeset = false; DrmMode mode; @@ -158,10 +132,6 @@ class DrmDisplayCompositor { DrmResources *drm_; int display_; - DrmCompositorWorker worker_; - FrameWorker frame_worker_; - - std::queue> composite_queue_; std::unique_ptr active_composition_; bool initialized_; @@ -178,7 +148,7 @@ class DrmDisplayCompositor { int squash_framebuffer_index_; DrmFramebuffer squash_framebuffers_[2]; - // mutable since we need to acquire in HaveQueuedComposites + // mutable since we need to acquire in Dump() mutable pthread_mutex_t lock_; // State tracking progress since our last Dump(). These are mutable since diff --git a/drmeventlistener.cpp b/drmeventlistener.cpp index 0514aa6..984d1dd 100644 --- a/drmeventlistener.cpp +++ b/drmeventlistener.cpp @@ -20,10 +20,13 @@ #include "drmresources.h" #include +#include #include #include #include +#include +#include #include namespace android { diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp index 8c853f4..762ee8c 100644 --- a/drmhwctwo.cpp +++ b/drmhwctwo.cpp @@ -557,7 +557,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *retire_fence) { i = overlay_planes.erase(i); } - ret = compositor_.QueueComposition(std::move(composition)); + ret = compositor_.ApplyComposition(std::move(composition)); if (ret) { ALOGE("Failed to apply the frame composition ret=%d", ret); return HWC2::Error::BadParameter; @@ -593,7 +593,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { compositor_.CreateComposition(); composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_); int ret = composition->SetDisplayMode(*mode); - ret = compositor_.QueueComposition(std::move(composition)); + ret = compositor_.ApplyComposition(std::move(composition)); if (ret) { ALOGE("Failed to queue dpms composition on %d", ret); return HWC2::Error::BadConfig; @@ -673,7 +673,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) { compositor_.CreateComposition(); composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_); composition->SetDpmsMode(dpms_value); - int ret = compositor_.QueueComposition(std::move(composition)); + int ret = compositor_.ApplyComposition(std::move(composition)); if (ret) { ALOGE("Failed to apply the dpms composition ret=%d", ret); return HWC2::Error::BadParameter; diff --git a/drmresources.cpp b/drmresources.cpp index 6b8ed03..762f5ef 100644 --- a/drmresources.cpp +++ b/drmresources.cpp @@ -35,7 +35,7 @@ namespace android { -DrmResources::DrmResources() : compositor_(this), event_listener_(this) { +DrmResources::DrmResources() : event_listener_(this) { } DrmResources::~DrmResources() { @@ -201,10 +201,6 @@ int DrmResources::Init() { if (ret) return ret; - ret = compositor_.Init(); - if (ret) - return ret; - ret = event_listener_.Init(); if (ret) { ALOGE("Can't initialize event listener %d", ret); @@ -333,54 +329,6 @@ int DrmResources::DestroyPropertyBlob(uint32_t blob_id) { return 0; } -int DrmResources::SetDisplayActiveMode(int display, const DrmMode &mode) { - std::unique_ptr comp(compositor_.CreateComposition(NULL)); - if (!comp) { - ALOGE("Failed to create composition for dpms on %d", display); - return -ENOMEM; - } - int ret = comp->SetDisplayMode(display, mode); - if (ret) { - ALOGE("Failed to add mode to composition on %d %d", display, ret); - return ret; - } - ret = compositor_.QueueComposition(std::move(comp)); - if (ret) { - ALOGE("Failed to queue dpms composition on %d %d", display, ret); - return ret; - } - return 0; -} - -int DrmResources::SetDpmsMode(int display, uint64_t mode) { - if (mode != DRM_MODE_DPMS_ON && mode != DRM_MODE_DPMS_OFF) { - ALOGE("Invalid dpms mode %" PRIu64, mode); - return -EINVAL; - } - - std::unique_ptr comp(compositor_.CreateComposition(NULL)); - if (!comp) { - ALOGE("Failed to create composition for dpms on %d", display); - return -ENOMEM; - } - int ret = comp->SetDpmsMode(display, mode); - if (ret) { - ALOGE("Failed to add dpms %" PRIu64 " to composition on %d %d", mode, - display, ret); - return ret; - } - ret = compositor_.QueueComposition(std::move(comp)); - if (ret) { - ALOGE("Failed to queue dpms composition on %d %d", display, ret); - return ret; - } - return 0; -} - -DrmCompositor *DrmResources::compositor() { - return &compositor_; -} - DrmEventListener *DrmResources::event_listener() { return &event_listener_; } diff --git a/drmresources.h b/drmresources.h index 011f87e..a2d8d16 100644 --- a/drmresources.h +++ b/drmresources.h @@ -17,7 +17,6 @@ #ifndef ANDROID_DRM_H_ #define ANDROID_DRM_H_ -#include "drmcompositor.h" #include "drmconnector.h" #include "drmcrtc.h" #include "drmencoder.h" @@ -58,7 +57,6 @@ class DrmResources { DrmConnector *GetConnectorForDisplay(int display) const; DrmCrtc *GetCrtcForDisplay(int display) const; DrmPlane *GetPlane(uint32_t id) const; - DrmCompositor *compositor(); DrmEventListener *event_listener(); int GetPlaneProperty(const DrmPlane &plane, const char *prop_name, @@ -69,8 +67,6 @@ class DrmResources { DrmProperty *property); uint32_t next_mode_id(); - int SetDisplayActiveMode(int display, const DrmMode &mode); - int SetDpmsMode(int display, uint64_t mode); int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id); int DestroyPropertyBlob(uint32_t blob_id); @@ -89,7 +85,6 @@ class DrmResources { std::vector> encoders_; std::vector> crtcs_; std::vector> planes_; - DrmCompositor compositor_; DrmEventListener event_listener_; std::pair min_resolution_; diff --git a/glworker.cpp b/glworker.cpp index e12995e..e90576a 100644 --- a/glworker.cpp +++ b/glworker.cpp @@ -143,6 +143,38 @@ static bool HasExtension(const char *extension, const char *extensions) { return false; } +int GLWorkerCompositor::BeginContext() { + private_.saved_egl_display = eglGetCurrentDisplay(); + private_.saved_egl_ctx = eglGetCurrentContext(); + + if (private_.saved_egl_display != egl_display_ || + private_.saved_egl_ctx != egl_ctx_) { + private_.saved_egl_read = eglGetCurrentSurface(EGL_READ); + private_.saved_egl_draw = eglGetCurrentSurface(EGL_DRAW); + } else { + return 0; + } + + if (!eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_ctx_)) { + ALOGE("BeginContext failed: %s", GetEGLError()); + return 1; + } + return 0; +} + +int GLWorkerCompositor::EndContext() { + if (private_.saved_egl_display != eglGetCurrentDisplay() || + private_.saved_egl_ctx != eglGetCurrentContext()) { + if (!eglMakeCurrent(private_.saved_egl_display, private_.saved_egl_read, + private_.saved_egl_draw, private_.saved_egl_ctx)) { + ALOGE("EndContext failed: %s", GetEGLError()); + return 1; + } + } + + return 0; +} + static AutoGLShader CompileAndCheckShader(GLenum type, unsigned source_count, const GLchar **sources, std::ostringstream *shader_log) { @@ -508,10 +540,9 @@ int GLWorkerCompositor::Init() { return 1; } - if (!eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_ctx_)) { - ALOGE("Failed to make the OpenGL ES Context current: %s", GetEGLError()); - return 1; - } + ret = BeginContext(); + if (ret) + return ret; gl_extensions = (const char *)glGetString(GL_EXTENSIONS); @@ -530,6 +561,9 @@ int GLWorkerCompositor::Init() { std::ostringstream shader_log; blend_programs_.emplace_back(GenerateProgram(1, &shader_log)); + + EndContext(); + if (blend_programs_.back().get() == 0) { ALOGE("%s", shader_log.str().c_str()); return 1; @@ -558,12 +592,17 @@ int GLWorkerCompositor::Composite(DrmHwcLayer *layers, return -EALREADY; } + ret = BeginContext(); + if (ret) + return -1; + GLint frame_width = framebuffer->getWidth(); GLint frame_height = framebuffer->getHeight(); CachedFramebuffer *cached_framebuffer = PrepareAndCacheFramebuffer(framebuffer); if (cached_framebuffer == NULL) { ALOGE("Composite failed because of failed framebuffer"); + EndContext(); return -EINVAL; } @@ -597,8 +636,10 @@ int GLWorkerCompositor::Composite(DrmHwcLayer *layers, } } - if (ret) + if (ret) { + EndContext(); return ret; + } glViewport(0, 0, frame_width, frame_height); @@ -676,6 +717,7 @@ int GLWorkerCompositor::Composite(DrmHwcLayer *layers, glBindFramebuffer(GL_FRAMEBUFFER, 0); + EndContext(); return ret; } diff --git a/glworker.h b/glworker.h index 158490c..26de55d 100644 --- a/glworker.h +++ b/glworker.h @@ -64,6 +64,16 @@ class GLWorkerCompositor { bool Promote(); }; + struct { + EGLDisplay saved_egl_display = EGL_NO_DISPLAY; + EGLContext saved_egl_ctx = EGL_NO_CONTEXT; + EGLSurface saved_egl_read = EGL_NO_SURFACE; + EGLSurface saved_egl_draw = EGL_NO_SURFACE; + } private_; + + int BeginContext(); + int EndContext(); + CachedFramebuffer *FindCachedFramebuffer( const sp &framebuffer); CachedFramebuffer *PrepareAndCacheFramebuffer(