From patchwork Fri May 4 19:18:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rob Herring (Arm)" X-Patchwork-Id: 10381461 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 AA38360159 for ; Fri, 4 May 2018 19:18:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8AEC4285FE for ; Fri, 4 May 2018 19:18:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7EBBC29545; Fri, 4 May 2018 19:18:49 +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=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, 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 2DEAA29544 for ; Fri, 4 May 2018 19:18:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C06B06E004; Fri, 4 May 2018 19:18:39 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-oi0-f54.google.com (mail-oi0-f54.google.com [209.85.218.54]) by gabe.freedesktop.org (Postfix) with ESMTPS id D64FD6E004 for ; Fri, 4 May 2018 19:18:38 +0000 (UTC) Received: by mail-oi0-f54.google.com with SMTP id l1-v6so20087661oii.1 for ; Fri, 04 May 2018 12:18:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=/pYPHpoLrHerBiRASK/EJh+feHKDzITOUi0e0rkl03Y=; b=XQzIDTOV4tjk0R8910+lhG49fDxjXu8fasMbbXpfd5opoZXYnXmLNUoliQ4u5vMnZ0 l8+YfSFiw9702daN+4BLxYPJ+DSSOi8xbimisBfKdOCOYoCu0O3AIduBBanWzx8A63hc EQyjmk0tQBMlI3Sy6nekcRQzrmdcTX0kQI+JDBauUurd7I8P7UX6E/xYxLu8Phpu5E3l fDy/JPBql1xxEytUiCREYnbV6MePE0cEjVyf7c2tnGvoYpgBtvpsqcGxRKtV21dI2sLI b6a0TH/OdjLOWwxZBPaUmDY/9mzCf4O0oLGVGTC4Wj+h3hAmRjUpAuTeYyg0MCYNuyoF zEDg== X-Gm-Message-State: ALQs6tAfFtqd9dx+iywn3A3ZkDzOCpTRwno87G9+iw52VCOeW97olWLT zlWyAZMAiFskllFS8JQn4Ntx54M= X-Google-Smtp-Source: AB8JxZoOQCyMUG5bNn3+Z/EWgPOtTJ9mLwHDgxdUbS7784voEqWP76XugXjRqorI+cTfdKBLnMOMXA== X-Received: by 2002:aca:1114:: with SMTP id 20-v6mr14515428oir.303.1525461515452; Fri, 04 May 2018 12:18:35 -0700 (PDT) Received: from xps15.herring.priv (216-188-254-6.dyn.grandenetworks.net. [216.188.254.6]) by smtp.googlemail.com with ESMTPSA id t48-v6sm704528otd.33.2018.05.04.12.18.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 04 May 2018 12:18:34 -0700 (PDT) From: Rob Herring To: dri-devel@lists.freedesktop.org Subject: [PATCH hwc] drm_hwcomposer: Remove GL compositing support Date: Fri, 4 May 2018 14:18:33 -0500 Message-Id: <20180504191833.6967-1-robh@kernel.org> X-Mailer: git-send-email 2.17.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Robert Foss , Alexandru-Cosmin Gheorghe , Sean Paul MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The GL based compositing adds alot of complexity and was only ever well tested on closed stacks. It also only supports GLES3.x and still relies on sw_sync timeline which is now a debugfs feature. Those are just the known issues. Removing the GL compositor means everything related to squashing layers and pre-compositing can be removed. The planner is left as it may be useful when adding back support for overlay planes. With this change, only a single plane is supported until ValidateDisplay learns to do atomic modesetting test for overlay planes. Signed-off-by: Rob Herring --- I've lightly tested this with virgl. John tested an earlier version on Hikey. This depends on reverting these commits: "drm_hwcomposer: Cleanup gl precompositor init and provide uses_GL flag" "drm_hwcomposer: Fall back to client compositon if the gl precompostior fails" Android.mk | 4 - autogl.h | 110 ----- drmcompositorworker.cpp | 78 ---- drmdisplaycomposition.cpp | 315 +------------- drmdisplaycomposition.h | 34 +- drmdisplaycompositor.cpp | 529 +---------------------- drmdisplaycompositor.h | 56 --- drmhwctwo.cpp | 6 +- glworker.cpp | 840 ----------------------------------- glworker.h | 94 ---- hwcomposer.cpp | 841 ------------------------------------ platform.cpp | 93 +--- platform.h | 49 +-- platformdrmgeneric.cpp | 17 - platformdrmgeneric.h | 1 - platformhisi.cpp | 23 - platformhisi.h | 1 - platformminigbm.cpp | 16 - platformminigbm.h | 1 - virtualcompositorworker.cpp | 168 ------- virtualcompositorworker.h | 56 --- 21 files changed, 21 insertions(+), 3311 deletions(-) delete mode 100644 autogl.h delete mode 100644 drmcompositorworker.cpp delete mode 100644 glworker.cpp delete mode 100644 glworker.h delete mode 100644 hwcomposer.cpp delete mode 100644 virtualcompositorworker.cpp delete mode 100644 virtualcompositorworker.h diff --git a/Android.mk b/Android.mk index c0a1d0e7cdce..0d05f9c52de5 100644 --- a/Android.mk +++ b/Android.mk @@ -37,8 +37,6 @@ include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := \ libcutils \ libdrm \ - libEGL \ - libGLESv2 \ libhardware \ liblog \ libsync \ @@ -63,12 +61,10 @@ LOCAL_SRC_FILES := \ drmmode.cpp \ drmplane.cpp \ drmproperty.cpp \ - glworker.cpp \ hwcutils.cpp \ platform.cpp \ platformdrmgeneric.cpp \ separate_rects.cpp \ - virtualcompositorworker.cpp \ vsyncworker.cpp LOCAL_CPPFLAGS += \ diff --git a/autogl.h b/autogl.h deleted file mode 100644 index fc77fb0c1bf0..000000000000 --- a/autogl.h +++ /dev/null @@ -1,110 +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_AUTO_GL_H_ -#define ANDROID_AUTO_GL_H_ - -#include -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES - -#include -#include -#include -#include - -// TODO(zachr): use hwc_drm_bo to turn buffer handles into textures -#ifndef EGL_NATIVE_HANDLE_ANDROID_NVX -#define EGL_NATIVE_HANDLE_ANDROID_NVX 0x322A -#endif - -namespace android { - -#define AUTO_GL_TYPE(name, type, zero, deleter) \ - struct name##Deleter { \ - typedef type pointer; \ - \ - void operator()(pointer p) const { \ - if (p != zero) { \ - deleter; \ - } \ - } \ - }; \ - typedef std::unique_ptr name; - -AUTO_GL_TYPE(AutoGLFramebuffer, GLuint, 0, glDeleteFramebuffers(1, &p)) -AUTO_GL_TYPE(AutoGLBuffer, GLuint, 0, glDeleteBuffers(1, &p)) -AUTO_GL_TYPE(AutoGLTexture, GLuint, 0, glDeleteTextures(1, &p)) -AUTO_GL_TYPE(AutoGLShader, GLint, 0, glDeleteShader(p)) -AUTO_GL_TYPE(AutoGLProgram, GLint, 0, glDeleteProgram(p)) - -struct AutoEGLDisplayImage { - AutoEGLDisplayImage() = default; - - AutoEGLDisplayImage(EGLDisplay display, EGLImageKHR image) - : display_(display), image_(image) { - } - - AutoEGLDisplayImage(const AutoEGLDisplayImage& rhs) = delete; - AutoEGLDisplayImage(AutoEGLDisplayImage&& rhs) { - display_ = rhs.display_; - image_ = rhs.image_; - rhs.display_ = EGL_NO_DISPLAY; - rhs.image_ = EGL_NO_IMAGE_KHR; - } - - ~AutoEGLDisplayImage() { - clear(); - } - - AutoEGLDisplayImage& operator=(const AutoEGLDisplayImage& rhs) = delete; - AutoEGLDisplayImage& operator=(AutoEGLDisplayImage&& rhs) { - clear(); - std::swap(display_, rhs.display_); - std::swap(image_, rhs.image_); - return *this; - } - - void reset(EGLDisplay display, EGLImageKHR image) { - clear(); - display_ = display; - image_ = image; - } - - void clear() { - if (image_ != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(display_, image_); - display_ = EGL_NO_DISPLAY; - image_ = EGL_NO_IMAGE_KHR; - } - } - - EGLImageKHR image() const { - return image_; - } - - private: - EGLDisplay display_ = EGL_NO_DISPLAY; - EGLImageKHR image_ = EGL_NO_IMAGE_KHR; -}; - -struct AutoEGLImageAndGLTexture { - AutoEGLDisplayImage image; - AutoGLTexture texture; -}; -} - -#endif diff --git a/drmcompositorworker.cpp b/drmcompositorworker.cpp deleted file mode 100644 index 695876d7ae70..000000000000 --- a/drmcompositorworker.cpp +++ /dev/null @@ -1,78 +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-worker" - -#include "drmdisplaycompositor.h" -#include "drmcompositorworker.h" -#include "worker.h" - -#include - -#include -#include - -namespace android { - -static const int64_t kSquashWait = 500000000LL; - -DrmCompositorWorker::DrmCompositorWorker(DrmDisplayCompositor *compositor) - : Worker("drm-compositor", HAL_PRIORITY_URGENT_DISPLAY), - compositor_(compositor) { -} - -DrmCompositorWorker::~DrmCompositorWorker() { -} - -int DrmCompositorWorker::Init() { - return InitWorker(); -} - -void DrmCompositorWorker::Routine() { - int ret; - if (!compositor_->HaveQueuedComposites()) { - Lock(); - - // Only use a timeout if we didn't do a SquashAll last time. This will - // prevent wait_ret == -ETIMEDOUT which would trigger a SquashAll and be a - // pointless drain on resources. - int wait_ret = did_squash_all_ ? WaitForSignalOrExitLocked() - : WaitForSignalOrExitLocked(kSquashWait); - Unlock(); - - switch (wait_ret) { - case 0: - break; - case -EINTR: - return; - case -ETIMEDOUT: - ret = compositor_->SquashAll(); - if (ret) - ALOGE("Failed to squash all %d", ret); - did_squash_all_ = true; - return; - default: - ALOGE("Failed to wait for signal, %d", wait_ret); - return; - } - } - - ret = compositor_->Composite(); - if (ret) - ALOGE("Failed to composite! %d", ret); - did_squash_all_ = false; -} -} diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp index 24a8e9c9a043..75e01a67564e 100644 --- a/drmdisplaycomposition.cpp +++ b/drmdisplaycomposition.cpp @@ -29,18 +29,12 @@ #include #include -#include #include #include namespace android { -DrmDisplayComposition::~DrmDisplayComposition() { - if (timeline_fd_ >= 0) { - SignalCompositionDone(); - close(timeline_fd_); - } -} +DrmDisplayComposition::~DrmDisplayComposition() {} int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc, Importer *importer, Planner *planner, @@ -51,12 +45,6 @@ int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc, planner_ = planner; frame_no_ = frame_no; - int ret = sw_sync_timeline_create(); - if (ret < 0) { - ALOGE("Failed to create sw sync timeline %d", ret); - return ret; - } - timeline_fd_ = ret; return 0; } @@ -64,26 +52,6 @@ bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) { return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des; } -int DrmDisplayComposition::CreateNextTimelineFence() { - ++timeline_; - return sw_sync_fence_create(timeline_fd_, "hwc drm display composition fence", - timeline_); -} - -int DrmDisplayComposition::IncreaseTimelineToPoint(int point) { - int timeline_increase = point - timeline_current_; - if (timeline_increase <= 0) - return 0; - - int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase); - if (ret) - ALOGE("Failed to increment sync timeline %d", ret); - else - timeline_current_ = point; - - return ret; -} - int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers, bool geometry_changed) { if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME)) @@ -122,252 +90,38 @@ int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) { return 0; } -static std::vector SetBitsToVector( - uint64_t in, const std::vector &index_map) { - std::vector out; - size_t msb = sizeof(in) * 8 - 1; - uint64_t mask = (uint64_t)1 << msb; - for (size_t i = msb; mask != (uint64_t)0; i--, mask >>= 1) - if (in & mask) - out.push_back(index_map[i]); - return out; -} - int DrmDisplayComposition::AddPlaneComposition(DrmCompositionPlane plane) { composition_planes_.emplace_back(std::move(plane)); return 0; } -void DrmDisplayComposition::SeparateLayers(DrmHwcRect *exclude_rects, - size_t num_exclude_rects) { - DrmCompositionPlane *comp = NULL; +void DrmDisplayComposition::SeparateLayers(DrmHwcRect *, + size_t ) { std::vector dedicated_layers; - // Go through the composition and find the precomp layer as well as any - // layers that have a dedicated plane located below the precomp layer. + // Go through the composition and find the layers that have a dedicated plane. for (auto &i : composition_planes_) { if (i.type() == DrmCompositionPlane::Type::kLayer) { dedicated_layers.insert(dedicated_layers.end(), i.source_layers().begin(), i.source_layers().end()); - } else if (i.type() == DrmCompositionPlane::Type::kPrecomp) { - comp = &i; - break; - } - } - if (!comp) - return; - - const std::vector &comp_layers = comp->source_layers(); - if (comp_layers.size() > 64) { - ALOGE("Failed to separate layers because there are more than 64"); - return; - } - - // Index at which the actual layers begin - size_t layer_offset = num_exclude_rects + dedicated_layers.size(); - if (comp_layers.size() + layer_offset > 64) { - ALOGW( - "Exclusion rectangles are being truncated to make the rectangle count " - "fit into 64"); - num_exclude_rects = 64 - comp_layers.size() - dedicated_layers.size(); - } - - // We inject all the exclude rects into the rects list. Any resulting rect - // that includes ANY of the first num_exclude_rects is rejected. After the - // exclude rects, we add the lower layers. The rects that intersect with - // these layers will be inspected and only those which are to be composited - // above the layer will be included in the composition regions. - std::vector> layer_rects(comp_layers.size() + layer_offset); - std::copy(exclude_rects, exclude_rects + num_exclude_rects, - layer_rects.begin()); - std::transform( - dedicated_layers.begin(), dedicated_layers.end(), - layer_rects.begin() + num_exclude_rects, - [=](size_t layer_index) { return layers_[layer_index].display_frame; }); - std::transform(comp_layers.begin(), comp_layers.end(), - layer_rects.begin() + layer_offset, [=](size_t layer_index) { - return layers_[layer_index].display_frame; - }); - - std::vector> separate_regions; - separate_rects::separate_rects_64(layer_rects, &separate_regions); - uint64_t exclude_mask = ((uint64_t)1 << num_exclude_rects) - 1; - uint64_t dedicated_mask = (((uint64_t)1 << dedicated_layers.size()) - 1) - << num_exclude_rects; - - for (separate_rects::RectSet ®ion : separate_regions) { - if (region.id_set.getBits() & exclude_mask) - continue; - - // If a rect intersects one of the dedicated layers, we need to remove the - // layers from the composition region which appear *below* the dedicated - // layer. This effectively punches a hole through the composition layer such - // that the dedicated layer can be placed below the composition and not - // be occluded. - uint64_t dedicated_intersect = region.id_set.getBits() & dedicated_mask; - for (size_t i = 0; dedicated_intersect && i < dedicated_layers.size(); - ++i) { - // Only exclude layers if they intersect this particular dedicated layer - if (!(dedicated_intersect & (1 << (i + num_exclude_rects)))) - continue; - - for (size_t j = 0; j < comp_layers.size(); ++j) { - if (comp_layers[j] < dedicated_layers[i]) - region.id_set.subtract(j + layer_offset); - } } - if (!(region.id_set.getBits() >> layer_offset)) - continue; - - pre_comp_regions_.emplace_back(DrmCompositionRegion{ - region.rect, - SetBitsToVector(region.id_set.getBits() >> layer_offset, comp_layers)}); } } -int DrmDisplayComposition::CreateAndAssignReleaseFences() { - std::unordered_set squash_layers; - std::unordered_set pre_comp_layers; - std::unordered_set comp_layers; - - for (const DrmCompositionRegion ®ion : squash_regions_) { - for (size_t source_layer_index : region.source_layers) { - DrmHwcLayer *source_layer = &layers_[source_layer_index]; - squash_layers.emplace(source_layer); - } - } - - for (const DrmCompositionRegion ®ion : pre_comp_regions_) { - for (size_t source_layer_index : region.source_layers) { - DrmHwcLayer *source_layer = &layers_[source_layer_index]; - pre_comp_layers.emplace(source_layer); - squash_layers.erase(source_layer); - } - } - - for (const DrmCompositionPlane &plane : composition_planes_) { - if (plane.type() == DrmCompositionPlane::Type::kLayer) { - for (auto i : plane.source_layers()) { - DrmHwcLayer *source_layer = &layers_[i]; - comp_layers.emplace(source_layer); - pre_comp_layers.erase(source_layer); - } - } - } - - for (DrmHwcLayer *layer : squash_layers) { - if (!layer->release_fence) - continue; - int ret = layer->release_fence.Set(CreateNextTimelineFence()); - if (ret < 0) { - ALOGE("Failed to set the release fence (squash) %d", ret); - return ret; - } - } - timeline_squash_done_ = timeline_; - - for (DrmHwcLayer *layer : pre_comp_layers) { - if (!layer->release_fence) - continue; - int ret = layer->release_fence.Set(CreateNextTimelineFence()); - if (ret < 0) - return ret; - } - timeline_pre_comp_done_ = timeline_; - - for (DrmHwcLayer *layer : comp_layers) { - if (!layer->release_fence) - continue; - int ret = layer->release_fence.Set(CreateNextTimelineFence()); - if (ret < 0) { - ALOGE("Failed to set the release fence (comp) %d", ret); - return ret; - } - } - - return 0; -} - -int DrmDisplayComposition::Plan(SquashState *squash, - std::vector *primary_planes, +int DrmDisplayComposition::Plan(std::vector *primary_planes, std::vector *overlay_planes) { if (type_ != DRM_COMPOSITION_TYPE_FRAME) return 0; - // Used to track which layers should be sent to the planner. We exclude layers - // that are entirely squashed so the planner can provision a precomposition - // layer as appropriate (ex: if 5 layers are squashed and 1 is not, we don't - // want to plan a precomposition layer that will be comprised of the already - // squashed layers). std::map to_composite; - bool use_squash_framebuffer = false; - // Used to determine which layers were entirely squashed - std::vector layer_squash_area(layers_.size(), 0); - // Used to avoid rerendering regions that were squashed - std::vector> exclude_rects; - if (squash != NULL) { - if (geometry_changed_) { - squash->Init(layers_.data(), layers_.size()); - } else { - std::vector changed_regions; - squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions); - - std::vector stable_regions; - squash->StableRegionsWithMarginalHistory(changed_regions, stable_regions); - - // Only if SOME region is stable - use_squash_framebuffer = - std::find(stable_regions.begin(), stable_regions.end(), true) != - stable_regions.end(); - - squash->RecordHistory(layers_.data(), layers_.size(), changed_regions); - - // Changes in which regions are squashed triggers a rerender via - // squash_regions. - bool render_squash = squash->RecordAndCompareSquashed(stable_regions); - - for (size_t region_index = 0; region_index < stable_regions.size(); - region_index++) { - const SquashState::Region ®ion = squash->regions()[region_index]; - if (!stable_regions[region_index]) - continue; - - exclude_rects.emplace_back(region.rect); - - if (render_squash) { - squash_regions_.emplace_back(); - squash_regions_.back().frame = region.rect; - } - - int frame_area = region.rect.area(); - // Source layers are sorted front to back i.e. top layer has lowest - // index. - for (size_t layer_index = layers_.size(); - layer_index-- > 0; // Yes, I double checked this - /* See condition */) { - if (!region.layer_refs[layer_index]) - continue; - layer_squash_area[layer_index] += frame_area; - if (render_squash) - squash_regions_.back().source_layers.push_back(layer_index); - } - } - } - - for (size_t i = 0; i < layers_.size(); ++i) { - if (layer_squash_area[i] < layers_[i].display_frame.area()) - to_composite.emplace(std::make_pair(i, &layers_[i])); - } - } else { - for (size_t i = 0; i < layers_.size(); ++i) - to_composite.emplace(std::make_pair(i, &layers_[i])); - } + for (size_t i = 0; i < layers_.size(); ++i) + to_composite.emplace(std::make_pair(i, &layers_[i])); int ret; std::vector plan; std::tie(ret, composition_planes_) = - planner_->ProvisionPlanes(to_composite, use_squash_framebuffer, crtc_, + planner_->ProvisionPlanes(to_composite, crtc_, primary_planes, overlay_planes); if (ret) { ALOGE("Planner failed provisioning planes ret=%d", ret); @@ -396,17 +150,7 @@ int DrmDisplayComposition::Plan(SquashState *squash, } } - return FinalizeComposition(exclude_rects.data(), exclude_rects.size()); -} - -int DrmDisplayComposition::FinalizeComposition() { - return FinalizeComposition(NULL, 0); -} - -int DrmDisplayComposition::FinalizeComposition(DrmHwcRect *exclude_rects, - size_t num_exclude_rects) { - SeparateLayers(exclude_rects, num_exclude_rects); - return CreateAndAssignReleaseFences(); + return 0; } static const char *DrmCompositionTypeToString(DrmCompositionType type) { @@ -506,23 +250,6 @@ static const char *BlendingToString(DrmHwcBlending blending) { } } -static void DumpRegion(const DrmCompositionRegion ®ion, - std::ostringstream *out) { - *out << "frame"; - region.frame.Dump(out); - *out << " source_layers=("; - - const std::vector &source_layers = region.source_layers; - for (size_t i = 0; i < source_layers.size(); i++) { - *out << source_layers[i]; - if (i < source_layers.size() - 1) { - *out << " "; - } - } - - *out << ")"; -} - void DrmDisplayComposition::Dump(std::ostringstream *out) const { *out << "----DrmDisplayComposition" << " crtc=" << (crtc_ ? crtc_->id() : -1) @@ -540,10 +267,6 @@ void DrmDisplayComposition::Dump(std::ostringstream *out) const { break; } - *out << " timeline[current/squash/pre-comp/done]=" << timeline_current_ << "/" - << timeline_squash_done_ << "/" << timeline_pre_comp_done_ << "/" - << timeline_ << "\n"; - *out << " Layers: count=" << layers_.size() << "\n"; for (size_t i = 0; i < layers_.size(); i++) { const DrmHwcLayer &layer = layers_[i]; @@ -578,12 +301,6 @@ void DrmDisplayComposition::Dump(std::ostringstream *out) const { case DrmCompositionPlane::Type::kLayer: *out << "LAYER"; break; - case DrmCompositionPlane::Type::kPrecomp: - *out << "PRECOMP"; - break; - case DrmCompositionPlane::Type::kSquash: - *out << "SQUASH"; - break; default: *out << ""; break; @@ -595,19 +312,5 @@ void DrmDisplayComposition::Dump(std::ostringstream *out) const { } *out << "\n"; } - - *out << " Squash Regions: count=" << squash_regions_.size() << "\n"; - for (size_t i = 0; i < squash_regions_.size(); i++) { - *out << " [" << i << "] "; - DumpRegion(squash_regions_[i], out); - *out << "\n"; - } - - *out << " Pre-Comp Regions: count=" << pre_comp_regions_.size() << "\n"; - for (size_t i = 0; i < pre_comp_regions_.size(); i++) { - *out << " [" << i << "] "; - DumpRegion(pre_comp_regions_[i], out); - *out << "\n"; - } } } diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h index 918392578753..b7fccb9cd283 100644 --- a/drmdisplaycomposition.h +++ b/drmdisplaycomposition.h @@ -20,7 +20,6 @@ #include "drmcrtc.h" #include "drmhwcomposer.h" #include "drmplane.h" -#include "glworker.h" #include #include @@ -62,8 +61,6 @@ class DrmCompositionPlane { enum class Type : int32_t { kDisable, kLayer, - kPrecomp, - kSquash, }; DrmCompositionPlane() = default; @@ -125,34 +122,15 @@ class DrmDisplayComposition { int SetDpmsMode(uint32_t dpms_mode); int SetDisplayMode(const DrmMode &display_mode); - int Plan(SquashState *squash, std::vector *primary_planes, + int Plan(std::vector *primary_planes, std::vector *overlay_planes); int FinalizeComposition(); - int CreateNextTimelineFence(); - int SignalSquashDone() { - return IncreaseTimelineToPoint(timeline_squash_done_); - } - int SignalPreCompDone() { - return IncreaseTimelineToPoint(timeline_pre_comp_done_); - } - int SignalCompositionDone() { - return IncreaseTimelineToPoint(timeline_); - } - std::vector &layers() { return layers_; } - std::vector &squash_regions() { - return squash_regions_; - } - - std::vector &pre_comp_regions() { - return pre_comp_regions_; - } - std::vector &composition_planes() { return composition_planes_; } @@ -202,12 +180,9 @@ class DrmDisplayComposition { private: bool validate_composition_type(DrmCompositionType desired); - int IncreaseTimelineToPoint(int point); - int FinalizeComposition(DrmHwcRect *exclude_rects, size_t num_exclude_rects); void SeparateLayers(DrmHwcRect *exclude_rects, size_t num_exclude_rects); - int CreateAndAssignReleaseFences(); DrmResources *drm_ = NULL; DrmCrtc *crtc_ = NULL; @@ -218,17 +193,10 @@ class DrmDisplayComposition { uint32_t dpms_mode_ = DRM_MODE_DPMS_ON; DrmMode display_mode_; - int timeline_fd_ = -1; - int timeline_ = 0; - int timeline_current_ = 0; - int timeline_squash_done_ = 0; - int timeline_pre_comp_done_ = 0; UniqueFd out_fence_ = -1; bool geometry_changed_; std::vector layers_; - std::vector squash_regions_; - std::vector pre_comp_regions_; std::vector composition_planes_; uint64_t frame_no_ = 0; diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp index e570923de942..34a729924fc6 100644 --- a/drmdisplaycompositor.cpp +++ b/drmdisplaycompositor.cpp @@ -35,153 +35,15 @@ #include "drmcrtc.h" #include "drmplane.h" #include "drmresources.h" -#include "glworker.h" namespace android { -void SquashState::Init(DrmHwcLayer *layers, size_t num_layers) { - generation_number_++; - valid_history_ = 0; - regions_.clear(); - last_handles_.clear(); - - std::vector> in_rects; - for (size_t i = 0; i < num_layers; i++) { - DrmHwcLayer *layer = &layers[i]; - in_rects.emplace_back(layer->display_frame); - last_handles_.push_back(layer->sf_handle); - } - - std::vector> out_regions; - separate_rects::separate_rects_64(in_rects, &out_regions); - - for (const separate_rects::RectSet &out_region : out_regions) { - regions_.emplace_back(); - Region ®ion = regions_.back(); - region.rect = out_region.rect; - region.layer_refs = out_region.id_set.getBits(); - } -} - -void SquashState::GenerateHistory(DrmHwcLayer *layers, size_t num_layers, - std::vector &changed_regions) const { - changed_regions.resize(regions_.size()); - if (num_layers != last_handles_.size()) { - ALOGE("SquashState::GenerateHistory expected %zu layers but got %zu layers", - last_handles_.size(), num_layers); - return; - } - std::bitset changed_layers; - for (size_t i = 0; i < last_handles_.size(); i++) { - DrmHwcLayer *layer = &layers[i]; - // Protected layers can't be squashed so we treat them as constantly - // changing. - if (layer->protected_usage() || last_handles_[i] != layer->sf_handle) - changed_layers.set(i); - } - - for (size_t i = 0; i < regions_.size(); i++) { - changed_regions[i] = (regions_[i].layer_refs & changed_layers).any(); - } -} - -void SquashState::StableRegionsWithMarginalHistory( - const std::vector &changed_regions, - std::vector &stable_regions) const { - stable_regions.resize(regions_.size()); - for (size_t i = 0; i < regions_.size(); i++) { - stable_regions[i] = !changed_regions[i] && is_stable(i); - } -} - -void SquashState::RecordHistory(DrmHwcLayer *layers, size_t num_layers, - const std::vector &changed_regions) { - if (num_layers != last_handles_.size()) { - ALOGE("SquashState::RecordHistory expected %zu layers but got %zu layers", - last_handles_.size(), num_layers); - return; - } - if (changed_regions.size() != regions_.size()) { - ALOGE("SquashState::RecordHistory expected %zu regions but got %zu regions", - regions_.size(), changed_regions.size()); - return; - } - - for (size_t i = 0; i < last_handles_.size(); i++) { - DrmHwcLayer *layer = &layers[i]; - last_handles_[i] = layer->sf_handle; - } - - for (size_t i = 0; i < regions_.size(); i++) { - regions_[i].change_history <<= 1; - regions_[i].change_history.set(/* LSB */ 0, changed_regions[i]); - } - - valid_history_++; -} - -bool SquashState::RecordAndCompareSquashed( - const std::vector &squashed_regions) { - if (squashed_regions.size() != regions_.size()) { - ALOGE( - "SquashState::RecordAndCompareSquashed expected %zu regions but got " - "%zu regions", - regions_.size(), squashed_regions.size()); - return false; - } - bool changed = false; - for (size_t i = 0; i < regions_.size(); i++) { - if (regions_[i].squashed != squashed_regions[i]) { - regions_[i].squashed = squashed_regions[i]; - changed = true; - } - } - return changed; -} - -void SquashState::Dump(std::ostringstream *out) const { - *out << "----SquashState generation=" << generation_number_ - << " history=" << valid_history_ << "\n" - << " Regions: count=" << regions_.size() << "\n"; - for (size_t i = 0; i < regions_.size(); i++) { - const Region ®ion = regions_[i]; - *out << " [" << i << "]" - << " history=" << region.change_history << " rect"; - region.rect.Dump(out); - *out << " layers=("; - bool first = true; - for (size_t layer_index = 0; layer_index < kMaxLayers; layer_index++) { - if ((region.layer_refs & - std::bitset((size_t)1 << layer_index)) - .any()) { - if (!first) - *out << " "; - first = false; - *out << layer_index; - } - } - *out << ")"; - if (region.squashed) - *out << " squashed"; - *out << "\n"; - } -} - -static bool UsesSquash(const std::vector &comp_planes) { - return std::any_of(comp_planes.begin(), comp_planes.end(), - [](const DrmCompositionPlane &plane) { - return plane.type() == DrmCompositionPlane::Type::kSquash; - }); -} - DrmDisplayCompositor::DrmDisplayCompositor() : drm_(NULL), display_(-1), initialized_(false), active_(false), use_hw_overlays_(true), - framebuffer_index_(0), - squash_framebuffer_index_(0), dump_frames_composited_(0), dump_last_timestamp_ns_(0) { struct timespec ts; @@ -244,112 +106,6 @@ DrmDisplayCompositor::GetActiveModeResolution() { return std::make_tuple(mode.h_display(), mode.v_display(), 0); } -int DrmDisplayCompositor::PrepareFramebuffer( - DrmFramebuffer &fb, DrmDisplayComposition *display_comp) { - int ret = fb.WaitReleased(-1); - if (ret) { - ALOGE("Failed to wait for framebuffer release %d", ret); - return ret; - } - uint32_t width, height; - std::tie(width, height, ret) = GetActiveModeResolution(); - if (ret) { - ALOGE( - "Failed to allocate framebuffer because the display resolution could " - "not be determined %d", - ret); - return ret; - } - - fb.set_release_fence_fd(-1); - if (!fb.Allocate(width, height)) { - ALOGE("Failed to allocate framebuffer with size %dx%d", width, height); - return -ENOMEM; - } - - display_comp->layers().emplace_back(); - DrmHwcLayer &pre_comp_layer = display_comp->layers().back(); - pre_comp_layer.sf_handle = fb.buffer()->handle; - pre_comp_layer.blending = DrmHwcBlending::kPreMult; - pre_comp_layer.source_crop = DrmHwcRect(0, 0, width, height); - pre_comp_layer.display_frame = DrmHwcRect(0, 0, width, height); - ret = pre_comp_layer.buffer.ImportBuffer(fb.buffer()->handle, - display_comp->importer()); - if (ret) { - ALOGE("Failed to import framebuffer for display %d", ret); - return ret; - } - - return ret; -} - -int DrmDisplayCompositor::ApplySquash(DrmDisplayComposition *display_comp) { - int ret = 0; - - DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_]; - ret = PrepareFramebuffer(fb, display_comp); - if (ret) { - ALOGE("Failed to prepare framebuffer for squash %d", ret); - return ret; - } - - std::vector ®ions = display_comp->squash_regions(); - ret = pre_compositor_->Composite(display_comp->layers().data(), - regions.data(), regions.size(), fb.buffer(), - display_comp->importer()); - pre_compositor_->Finish(); - - if (ret) { - ALOGE("Failed to squash layers"); - return ret; - } - - ret = display_comp->CreateNextTimelineFence(); - if (ret <= 0) { - ALOGE("Failed to create squash framebuffer release fence %d", ret); - return ret; - } - - fb.set_release_fence_fd(ret); - display_comp->SignalSquashDone(); - - return 0; -} - -int DrmDisplayCompositor::ApplyPreComposite( - DrmDisplayComposition *display_comp) { - int ret = 0; - - DrmFramebuffer &fb = framebuffers_[framebuffer_index_]; - ret = PrepareFramebuffer(fb, display_comp); - if (ret) { - ALOGE("Failed to prepare framebuffer for pre-composite %d", ret); - return ret; - } - - std::vector ®ions = display_comp->pre_comp_regions(); - ret = pre_compositor_->Composite(display_comp->layers().data(), - regions.data(), regions.size(), fb.buffer(), - display_comp->importer()); - pre_compositor_->Finish(); - - if (ret) { - ALOGE("Failed to pre-composite layers"); - return ret; - } - - ret = display_comp->CreateNextTimelineFence(); - if (ret <= 0) { - ALOGE("Failed to create pre-composite framebuffer release fence %d", ret); - return ret; - } - - fb.set_release_fence_fd(ret); - display_comp->SignalPreCompDone(); - - return 0; -} - int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); if (!pset) { @@ -384,103 +140,6 @@ int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { return 0; } -int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) { - int ret = 0; - - std::vector &layers = display_comp->layers(); - std::vector &comp_planes = - display_comp->composition_planes(); - std::vector &squash_regions = - display_comp->squash_regions(); - 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; - ret = ApplySquash(display_comp); - if (ret) - return ret; - - squash_layer_index = layers.size() - 1; - } else { - if (UsesSquash(comp_planes)) { - DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_]; - layers.emplace_back(); - squash_layer_index = layers.size() - 1; - DrmHwcLayer &squash_layer = layers.back(); - ret = squash_layer.buffer.ImportBuffer(fb.buffer()->handle, - display_comp->importer()); - if (ret) { - ALOGE("Failed to import old squashed framebuffer %d", ret); - return ret; - } - squash_layer.sf_handle = fb.buffer()->handle; - squash_layer.blending = DrmHwcBlending::kPreMult; - squash_layer.source_crop = DrmHwcRect( - 0, 0, squash_layer.buffer->width, squash_layer.buffer->height); - squash_layer.display_frame = DrmHwcRect( - 0, 0, squash_layer.buffer->width, squash_layer.buffer->height); - ret = display_comp->CreateNextTimelineFence(); - - if (ret <= 0) { - ALOGE("Failed to create squash framebuffer release fence %d", ret); - return ret; - } - - fb.set_release_fence_fd(ret); - ret = 0; - } - } - - bool do_pre_comp = pre_comp_regions.size() > 0; - int pre_comp_layer_index = -1; - if (do_pre_comp) { - ret = ApplyPreComposite(display_comp); - if (ret) - return ret; - - pre_comp_layer_index = layers.size() - 1; - framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; - } - - for (DrmCompositionPlane &comp_plane : comp_planes) { - std::vector &source_layers = comp_plane.source_layers(); - switch (comp_plane.type()) { - case DrmCompositionPlane::Type::kSquash: - if (source_layers.size()) - ALOGE("Squash source_layers is expected to be empty (%zu/%d)", - source_layers[0], squash_layer_index); - source_layers.push_back(squash_layer_index); - break; - case DrmCompositionPlane::Type::kPrecomp: - if (!do_pre_comp) { - ALOGE( - "Can not use pre composite framebuffer with no pre composite " - "regions"); - return -EINVAL; - } - // Replace source_layers with the output of the precomposite - source_layers.clear(); - source_layers.push_back(pre_comp_layer_index); - break; - default: - break; - } - } - - return ret; -} - int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, bool test_only) { ATRACE_CALL(); @@ -778,8 +437,6 @@ void DrmDisplayCompositor::ClearDisplay() { if (DisablePlanes(active_composition_.get())) return; - active_composition_->SignalCompositionDone(); - active_composition_.reset(NULL); } @@ -799,9 +456,6 @@ void DrmDisplayCompositor::ApplyFrame( } ++dump_frames_composited_; - if (active_composition_) - active_composition_->SignalCompositionDone(); - ret = pthread_mutex_lock(&lock_); if (ret) ALOGE("Failed to acquire lock for active_composition swap"); @@ -819,38 +473,16 @@ int DrmDisplayCompositor::ApplyComposition( int ret = 0; switch (composition->type()) { case DRM_COMPOSITION_TYPE_FRAME: - ret = PrepareFrame(composition.get()); - if (ret) { - ALOGE("Failed to prepare frame for display %d", display_); - return ret; - } if (composition->geometry_changed()) { // Send the composition to the kernel to ensure we can commit it. This - // is just a test, it won't actually commit the frame. If rejected, - // squash the frame into one layer and use the squashed composition + // is just a test, it won't actually commit the frame. ret = CommitFrame(composition.get(), true); - if (ret) - ALOGI("Commit test failed, squashing frame for display %d", display_); - use_hw_overlays_ = !ret; - } - - // If use_hw_overlays_ is false, we can't use hardware to composite the - // frame. So squash all layers into a single composition and apply that - // instead. - if (!use_hw_overlays_) { - std::unique_ptr squashed = CreateComposition(); - ret = SquashFrame(composition.get(), squashed.get()); - if (!ret) { - composition = std::move(squashed); - } else { - ALOGE("Failed to squash frame for display %d", display_); - // Disable the hw used by the last active composition. This allows us - // to signal the release fences from that composition to avoid - // hanging. - ClearDisplay(); + if (ret) { + ALOGE("Commit test failed for display %d, FIXME", display_); return ret; } } + ApplyFrame(std::move(composition), ret); break; case DRM_COMPOSITION_TYPE_DPMS: @@ -878,154 +510,6 @@ int DrmDisplayCompositor::ApplyComposition( return ret; } -int DrmDisplayCompositor::SquashAll() { - AutoLock lock(&lock_, "compositor"); - int ret = lock.Lock(); - if (ret) - return ret; - - if (!active_composition_) - return 0; - - std::unique_ptr comp = CreateComposition(); - ret = SquashFrame(active_composition_.get(), comp.get()); - - // ApplyFrame needs the lock - lock.Unlock(); - - if (!ret) - ApplyFrame(std::move(comp), 0); - - return ret; -} - -// Returns: -// - 0 if src is successfully squashed into dst -// - -EALREADY if the src is already squashed -// - Appropriate error if the squash fails -int DrmDisplayCompositor::SquashFrame(DrmDisplayComposition *src, - DrmDisplayComposition *dst) { - if (src->type() != DRM_COMPOSITION_TYPE_FRAME) - return -ENOTSUP; - - std::vector &src_planes = src->composition_planes(); - std::vector &src_layers = src->layers(); - - // Make sure there is more than one layer to squash. - size_t src_planes_with_layer = std::count_if( - src_planes.begin(), src_planes.end(), [](DrmCompositionPlane &p) { - return p.type() != DrmCompositionPlane::Type::kDisable; - }); - if (src_planes_with_layer <= 1) - return -EALREADY; - - int pre_comp_layer_index; - - int ret = dst->Init(drm_, src->crtc(), src->importer(), src->planner(), - src->frame_no()); - if (ret) { - ALOGE("Failed to init squash all composition %d", ret); - return ret; - } - - DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kPrecomp, NULL, - src->crtc()); - std::vector dst_layers; - for (DrmCompositionPlane &comp_plane : src_planes) { - // Composition planes without DRM planes should never happen - if (comp_plane.plane() == NULL) { - ALOGE("Skipping squash all because of NULL plane"); - ret = -EINVAL; - goto move_layers_back; - } - - if (comp_plane.plane()->type() == DRM_PLANE_TYPE_PRIMARY) - squashed_comp.set_plane(comp_plane.plane()); - else - dst->AddPlaneDisable(comp_plane.plane()); - - if (comp_plane.type() == DrmCompositionPlane::Type::kDisable) - continue; - - for (auto i : comp_plane.source_layers()) { - DrmHwcLayer &layer = src_layers[i]; - - // Squashing protected layers is impossible. - if (layer.protected_usage()) { - ret = -ENOTSUP; - goto move_layers_back; - } - - // The OutputFds point to freed memory after hwc_set returns. They are - // returned to the default to prevent DrmDisplayComposition::Plan from - // filling the OutputFds. - layer.release_fence = OutputFd(); - dst_layers.emplace_back(std::move(layer)); - squashed_comp.source_layers().push_back( - squashed_comp.source_layers().size()); - } - } - - if (squashed_comp.plane() == NULL) { - ALOGE("Primary plane not found for squash"); - ret = -ENOTSUP; - goto move_layers_back; - } - - ret = dst->SetLayers(dst_layers.data(), dst_layers.size(), false); - if (ret) { - ALOGE("Failed to set layers for squash all composition %d", ret); - goto move_layers_back; - } - - ret = dst->AddPlaneComposition(std::move(squashed_comp)); - if (ret) { - ALOGE("Failed to add squashed plane composition %d", ret); - goto move_layers_back; - } - - ret = dst->FinalizeComposition(); - if (ret) { - ALOGE("Failed to plan for squash all composition %d", ret); - goto move_layers_back; - } - - ret = ApplyPreComposite(dst); - if (ret) { - ALOGE("Failed to pre-composite for squash all composition %d", ret); - goto move_layers_back; - } - - pre_comp_layer_index = dst->layers().size() - 1; - framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; - - for (DrmCompositionPlane &plane : dst->composition_planes()) { - if (plane.type() == DrmCompositionPlane::Type::kPrecomp) { - // Replace source_layers with the output of the precomposite - plane.source_layers().clear(); - plane.source_layers().push_back(pre_comp_layer_index); - break; - } - } - - return 0; - -// TODO(zachr): think of a better way to transfer ownership back to the active -// composition. -move_layers_back: - for (size_t plane_index = 0; - plane_index < src_planes.size() && plane_index < dst_layers.size();) { - if (src_planes[plane_index].source_layers().empty()) { - plane_index++; - continue; - } - for (auto i : src_planes[plane_index].source_layers()) - src_layers[i] = std::move(dst_layers[plane_index++]); - } - - return ret; -} - void DrmDisplayCompositor::Dump(std::ostringstream *out) const { int ret = pthread_mutex_lock(&lock_); if (ret) @@ -1051,11 +535,6 @@ void DrmDisplayCompositor::Dump(std::ostringstream *out) const { dump_last_timestamp_ns_ = cur_ts; - if (active_composition_) - active_composition_->Dump(out); - - squash_state_.Dump(out); - pthread_mutex_unlock(&lock_); } } diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h index f1965fb0ad7f..eaf82fca989d 100644 --- a/drmdisplaycompositor.h +++ b/drmdisplaycompositor.h @@ -36,49 +36,6 @@ namespace android { -class GLWorkerCompositor; - -class SquashState { - public: - static const unsigned kHistoryLength = 6; // TODO: make this number not magic - static const unsigned kMaxLayers = 64; - - struct Region { - DrmHwcRect rect; - std::bitset layer_refs; - std::bitset change_history; - bool squashed = false; - }; - - bool is_stable(int region_index) const { - return valid_history_ >= kHistoryLength && - regions_[region_index].change_history.none(); - } - - const std::vector ®ions() const { - return regions_; - } - - void Init(DrmHwcLayer *layers, size_t num_layers); - void GenerateHistory(DrmHwcLayer *layers, size_t num_layers, - std::vector &changed_regions) const; - void StableRegionsWithMarginalHistory( - const std::vector &changed_regions, - std::vector &stable_regions) const; - void RecordHistory(DrmHwcLayer *layers, size_t num_layers, - const std::vector &changed_regions); - bool RecordAndCompareSquashed(const std::vector &squashed_regions); - - void Dump(std::ostringstream *out) const; - - private: - size_t generation_number_ = 0; - unsigned valid_history_ = 0; - std::vector last_handles_; - - std::vector regions_; -}; - class DrmDisplayCompositor { public: DrmDisplayCompositor(); @@ -89,15 +46,10 @@ class DrmDisplayCompositor { std::unique_ptr CreateComposition() const; int ApplyComposition(std::unique_ptr composition); int Composite(); - int SquashAll(); void Dump(std::ostringstream *out) const; std::tuple GetActiveModeResolution(); - SquashState *squash_state() { - return &squash_state_; - } - private: struct ModeState { bool needs_modeset = false; @@ -115,11 +67,8 @@ class DrmDisplayCompositor { int PrepareFramebuffer(DrmFramebuffer &fb, DrmDisplayComposition *display_comp); - int ApplySquash(DrmDisplayComposition *display_comp); - int ApplyPreComposite(DrmDisplayComposition *display_comp); int PrepareFrame(DrmDisplayComposition *display_comp); int CommitFrame(DrmDisplayComposition *display_comp, bool test_only); - int SquashFrame(DrmDisplayComposition *src, DrmDisplayComposition *dst); int ApplyDpms(DrmDisplayComposition *display_comp); int DisablePlanes(DrmDisplayComposition *display_comp); @@ -142,11 +91,6 @@ class DrmDisplayCompositor { int framebuffer_index_; DrmFramebuffer framebuffers_[DRM_DISPLAY_BUFFERS]; - std::unique_ptr pre_compositor_; - - SquashState squash_state_; - int squash_framebuffer_index_; - DrmFramebuffer squash_framebuffers_[2]; // mutable since we need to acquire in Dump() mutable pthread_mutex_t lock_; diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp index 8e00d7150217..60ff384e9a08 100644 --- a/drmhwctwo.cpp +++ b/drmhwctwo.cpp @@ -539,7 +539,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *retire_fence) { std::vector primary_planes(primary_planes_); std::vector overlay_planes(overlay_planes_); - ret = composition->Plan(compositor_.squash_state(), &primary_planes, + ret = composition->Plan(&primary_planes, &overlay_planes); if (ret) { ALOGE("Failed to plan the composition ret=%d", ret); @@ -692,12 +692,10 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types, case HWC2::Composition::SolidColor: case HWC2::Composition::Cursor: case HWC2::Composition::Sideband: + default: layer.set_validated_type(HWC2::Composition::Client); ++*num_types; break; - default: - layer.set_validated_type(layer.sf_type()); - break; } } return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; diff --git a/glworker.cpp b/glworker.cpp deleted file mode 100644 index ca726bf573ba..000000000000 --- a/glworker.cpp +++ /dev/null @@ -1,840 +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 ATRACE_TAG ATRACE_TAG_GRAPHICS -#define LOG_TAG "hwc-gl-worker" - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include -#include - -#include - -#include "drmdisplaycomposition.h" -#include "platform.h" - -#include "glworker.h" - -#define MAX_OVERLAPPING_LAYERS 64 - -namespace android { - -// clang-format off -// Column-major order: -// float mat[4] = { 1, 2, 3, 4 } === -// [ 1 3 ] -// [ 2 4 ] -float kTextureTransformMatrices[] = { - 1.0f, 0.0f, 0.0f, 1.0f, // identity matrix - 0.0f, 1.0f, 1.0f, 0.0f, // swap x and y -}; -// clang-format on - -static const char *GetGLError(void) { - switch (glGetError()) { - case GL_NO_ERROR: - return "GL_NO_ERROR"; - case GL_INVALID_ENUM: - return "GL_INVALID_ENUM"; - case GL_INVALID_VALUE: - return "GL_INVALID_VALUE"; - case GL_INVALID_OPERATION: - return "GL_INVALID_OPERATION"; - case GL_INVALID_FRAMEBUFFER_OPERATION: - return "GL_INVALID_FRAMEBUFFER_OPERATION"; - case GL_OUT_OF_MEMORY: - return "GL_OUT_OF_MEMORY"; - default: - return "Unknown error"; - } -} - -static const char *GetGLFramebufferError(void) { - switch (glCheckFramebufferStatus(GL_FRAMEBUFFER)) { - case GL_FRAMEBUFFER_COMPLETE: - return "GL_FRAMEBUFFER_COMPLETE"; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; - case GL_FRAMEBUFFER_UNSUPPORTED: - return "GL_FRAMEBUFFER_UNSUPPORTED"; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; - default: - return "Unknown error"; - } -} - -static const char *GetEGLError(void) { - switch (eglGetError()) { - case EGL_SUCCESS: - return "EGL_SUCCESS"; - case EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED"; - case EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS"; - case EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE"; - case EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT"; - case EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG"; - case EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY"; - case EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE"; - case EGL_BAD_MATCH: - return "EGL_BAD_MATCH"; - case EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER"; - case EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW"; - case EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST"; - default: - return "Unknown error"; - } -} - -static bool HasExtension(const char *extension, const char *extensions) { - const char *start, *where, *terminator; - start = extensions; - for (;;) { - where = (char *)strstr((const char *)start, extension); - if (!where) - break; - terminator = where + strlen(extension); - if (where == start || *(where - 1) == ' ') - if (*terminator == ' ' || *terminator == '\0') - return true; - start = terminator; - } - 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) { - GLint status; - AutoGLShader shader(glCreateShader(type)); - if (shader.get() == 0) { - if (shader_log) - *shader_log << "Failed glCreateShader call"; - return 0; - } - - glShaderSource(shader.get(), source_count, sources, NULL); - glCompileShader(shader.get()); - glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status); - if (!status) { - if (shader_log) { - GLint log_length; - glGetShaderiv(shader.get(), GL_INFO_LOG_LENGTH, &log_length); - std::string info_log(log_length, ' '); - glGetShaderInfoLog(shader.get(), log_length, NULL, &info_log.front()); - *shader_log << "Failed to compile shader:\n" << info_log.c_str() - << "\nShader Source:\n"; - for (unsigned i = 0; i < source_count; i++) { - *shader_log << sources[i]; - } - *shader_log << "\n"; - } - return 0; - } - - return shader; -} - -static std::string GenerateVertexShader(int layer_count) { - std::ostringstream vertex_shader_stream; - vertex_shader_stream - << "#version 300 es\n" - << "#define LAYER_COUNT " << layer_count << "\n" - << "precision mediump int;\n" - << "uniform vec4 uViewport;\n" - << "uniform vec4 uLayerCrop[LAYER_COUNT];\n" - << "uniform mat2 uTexMatrix[LAYER_COUNT];\n" - << "in vec2 vPosition;\n" - << "in vec2 vTexCoords;\n" - << "out vec2 fTexCoords[LAYER_COUNT];\n" - << "void main() {\n" - << " for (int i = 0; i < LAYER_COUNT; i++) {\n" - << " vec2 tempCoords = vTexCoords * uTexMatrix[i];\n" - << " fTexCoords[i] =\n" - << " uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw;\n" - << " }\n" - << " vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw;\n" - << " gl_Position =\n" - << " vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0);\n" - << "}\n"; - return vertex_shader_stream.str(); -} - -static std::string GenerateFragmentShader(int layer_count) { - std::ostringstream fragment_shader_stream; - fragment_shader_stream << "#version 300 es\n" - << "#define LAYER_COUNT " << layer_count << "\n" - << "#extension GL_OES_EGL_image_external : require\n" - << "precision mediump float;\n"; - for (int i = 0; i < layer_count; ++i) { - fragment_shader_stream << "uniform samplerExternalOES uLayerTexture" << i - << ";\n"; - } - fragment_shader_stream << "uniform float uLayerAlpha[LAYER_COUNT];\n" - << "uniform float uLayerPremult[LAYER_COUNT];\n" - << "in vec2 fTexCoords[LAYER_COUNT];\n" - << "out vec4 oFragColor;\n" - << "void main() {\n" - << " vec3 color = vec3(0.0, 0.0, 0.0);\n" - << " float alphaCover = 1.0;\n" - << " vec4 texSample;\n" - << " vec3 multRgb;\n"; - for (int i = 0; i < layer_count; ++i) { - if (i > 0) - fragment_shader_stream << " if (alphaCover > 0.5/255.0) {\n"; - // clang-format off - fragment_shader_stream - << " texSample = texture2D(uLayerTexture" << i << ",\n" - << " fTexCoords[" << i << "]);\n" - << " multRgb = texSample.rgb *\n" - << " max(texSample.a, uLayerPremult[" << i << "]);\n" - << " color += multRgb * uLayerAlpha[" << i << "] * alphaCover;\n" - << " alphaCover *= 1.0 - texSample.a * uLayerAlpha[" << i << "];\n"; - // clang-format on - } - for (int i = 0; i < layer_count - 1; ++i) - fragment_shader_stream << " }\n"; - fragment_shader_stream << " oFragColor = vec4(color, 1.0 - alphaCover);\n" - << "}\n"; - return fragment_shader_stream.str(); -} - -static AutoGLProgram GenerateProgram(unsigned num_textures, - std::ostringstream *shader_log) { - std::string vertex_shader_string = GenerateVertexShader(num_textures); - const GLchar *vertex_shader_source = vertex_shader_string.c_str(); - AutoGLShader vertex_shader = CompileAndCheckShader( - GL_VERTEX_SHADER, 1, &vertex_shader_source, shader_log); - if (!vertex_shader.get()) - return 0; - - std::string fragment_shader_string = GenerateFragmentShader(num_textures); - const GLchar *fragment_shader_source = fragment_shader_string.c_str(); - AutoGLShader fragment_shader = CompileAndCheckShader( - GL_FRAGMENT_SHADER, 1, &fragment_shader_source, shader_log); - if (!fragment_shader.get()) - return 0; - - AutoGLProgram program(glCreateProgram()); - if (!program.get()) { - if (shader_log) - *shader_log << "Failed to create program: " << GetGLError() << "\n"; - return 0; - } - - glAttachShader(program.get(), vertex_shader.get()); - glAttachShader(program.get(), fragment_shader.get()); - glBindAttribLocation(program.get(), 0, "vPosition"); - glBindAttribLocation(program.get(), 1, "vTexCoords"); - glLinkProgram(program.get()); - glDetachShader(program.get(), vertex_shader.get()); - glDetachShader(program.get(), fragment_shader.get()); - - GLint status; - glGetProgramiv(program.get(), GL_LINK_STATUS, &status); - if (!status) { - if (shader_log) { - GLint log_length; - glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &log_length); - std::string program_log(log_length, ' '); - glGetProgramInfoLog(program.get(), log_length, NULL, - &program_log.front()); - *shader_log << "Failed to link program:\n" << program_log.c_str() << "\n"; - } - return 0; - } - - return program; -} - -struct RenderingCommand { - struct TextureSource { - unsigned texture_index; - float crop_bounds[4]; - float alpha; - float premult; - float texture_matrix[4]; - }; - - float bounds[4]; - unsigned texture_count = 0; - TextureSource textures[MAX_OVERLAPPING_LAYERS]; -}; - -static void ConstructCommand(const DrmHwcLayer *layers, - const DrmCompositionRegion ®ion, - RenderingCommand &cmd) { - std::copy_n(region.frame.bounds, 4, cmd.bounds); - - for (size_t texture_index : region.source_layers) { - const DrmHwcLayer &layer = layers[texture_index]; - - DrmHwcRect display_rect(layer.display_frame); - float display_size[2] = {display_rect.bounds[2] - display_rect.bounds[0], - display_rect.bounds[3] - display_rect.bounds[1]}; - - float tex_width = layer.buffer->width; - float tex_height = layer.buffer->height; - DrmHwcRect crop_rect(layer.source_crop.left / tex_width, - layer.source_crop.top / tex_height, - layer.source_crop.right / tex_width, - layer.source_crop.bottom / tex_height); - - float crop_size[2] = {crop_rect.bounds[2] - crop_rect.bounds[0], - crop_rect.bounds[3] - crop_rect.bounds[1]}; - - RenderingCommand::TextureSource &src = cmd.textures[cmd.texture_count]; - cmd.texture_count++; - src.texture_index = texture_index; - - bool swap_xy = false; - bool flip_xy[2] = { false, false }; - - if (layer.transform == DrmHwcTransform::kRotate180) { - swap_xy = false; - flip_xy[0] = true; - flip_xy[1] = true; - } else if (layer.transform == DrmHwcTransform::kRotate270) { - swap_xy = true; - flip_xy[0] = true; - flip_xy[1] = false; - } else if (layer.transform & DrmHwcTransform::kRotate90) { - swap_xy = true; - if (layer.transform & DrmHwcTransform::kFlipH) { - flip_xy[0] = true; - flip_xy[1] = true; - } else if (layer.transform & DrmHwcTransform::kFlipV) { - flip_xy[0] = false; - flip_xy[1] = false; - } else { - flip_xy[0] = false; - flip_xy[1] = true; - } - } else { - if (layer.transform & DrmHwcTransform::kFlipH) - flip_xy[0] = true; - if (layer.transform & DrmHwcTransform::kFlipV) - flip_xy[1] = true; - } - - if (swap_xy) - std::copy_n(&kTextureTransformMatrices[4], 4, src.texture_matrix); - else - std::copy_n(&kTextureTransformMatrices[0], 4, src.texture_matrix); - - for (int j = 0; j < 4; j++) { - int b = j ^ (swap_xy ? 1 : 0); - float bound_percent = - (cmd.bounds[b] - display_rect.bounds[b % 2]) / display_size[b % 2]; - if (flip_xy[j % 2]) { - src.crop_bounds[j] = - crop_rect.bounds[j % 2 + 2] - bound_percent * crop_size[j % 2]; - } else { - src.crop_bounds[j] = - crop_rect.bounds[j % 2] + bound_percent * crop_size[j % 2]; - } - } - - if (layer.blending == DrmHwcBlending::kNone) { - src.alpha = src.premult = 1.0f; - // This layer is opaque. There is no point in using layers below this one. - break; - } - - src.alpha = layer.alpha / 255.0f; - src.premult = (layer.blending == DrmHwcBlending::kPreMult) ? 1.0f : 0.0f; - } -} - -static int EGLFenceWait(EGLDisplay egl_display, int acquireFenceFd) { - int ret = 0; - - EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, acquireFenceFd, - EGL_NONE}; - EGLSyncKHR egl_sync = - eglCreateSyncKHR(egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); - if (egl_sync == EGL_NO_SYNC_KHR) { - ALOGE("Failed to make EGLSyncKHR from acquireFenceFd: %s", GetEGLError()); - close(acquireFenceFd); - return 1; - } - - EGLint success = eglWaitSyncKHR(egl_display, egl_sync, 0); - if (success == EGL_FALSE) { - ALOGE("Failed to wait for acquire: %s", GetEGLError()); - ret = 1; - } - eglDestroySyncKHR(egl_display, egl_sync); - - return ret; -} - -static int CreateTextureFromHandle(EGLDisplay egl_display, - buffer_handle_t handle, - Importer *importer, - AutoEGLImageAndGLTexture *out) { - EGLImageKHR image = importer->ImportImage(egl_display, handle); - - if (image == EGL_NO_IMAGE_KHR) { - ALOGE("Failed to make image %s %p", GetEGLError(), handle); - return -EINVAL; - } - - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_REPEAT); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); - - out->image.reset(egl_display, image); - out->texture.reset(texture); - - return 0; -} - -GLWorkerCompositor::GLWorkerCompositor() - : egl_display_(EGL_NO_DISPLAY), egl_ctx_(EGL_NO_CONTEXT) { -} - -int GLWorkerCompositor::Init() { - int ret = 0; - const char *egl_extensions; - const char *gl_extensions; - EGLint num_configs; - EGLConfig egl_config; - - // clang-format off - const GLfloat verts[] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 2.0f, 0.0f, 2.0f, - 2.0f, 0.0f, 2.0f, 0.0f - }; - // clang-format on - - const EGLint config_attribs[] = {EGL_RENDERABLE_TYPE, - EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, - 8, - EGL_GREEN_SIZE, - 8, - EGL_BLUE_SIZE, - 8, - EGL_NONE}; - - const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; - - egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (egl_display_ == EGL_NO_DISPLAY) { - ALOGE("Failed to get egl display"); - return 1; - } - - if (!eglInitialize(egl_display_, NULL, NULL)) { - ALOGE("Failed to initialize egl: %s", GetEGLError()); - return 1; - } - - egl_extensions = eglQueryString(egl_display_, EGL_EXTENSIONS); - - // These extensions are all technically required but not always reported due - // to meta EGL filtering them out. - if (!HasExtension("EGL_KHR_image_base", egl_extensions)) - ALOGW("EGL_KHR_image_base extension not supported"); - - if (!HasExtension("EGL_ANDROID_image_native_buffer", egl_extensions)) - ALOGW("EGL_ANDROID_image_native_buffer extension not supported"); - - if (!HasExtension("EGL_ANDROID_native_fence_sync", egl_extensions)) - ALOGW("EGL_ANDROID_native_fence_sync extension not supported"); - - if (!eglChooseConfig(egl_display_, config_attribs, &egl_config, 1, - &num_configs)) { - ALOGE("eglChooseConfig() failed with error: %s", GetEGLError()); - return 1; - } - - egl_ctx_ = - eglCreateContext(egl_display_, egl_config, - EGL_NO_CONTEXT /* No shared context */, context_attribs); - - if (egl_ctx_ == EGL_NO_CONTEXT) { - ALOGE("Failed to create OpenGL ES Context: %s", GetEGLError()); - return 1; - } - - ret = BeginContext(); - if (ret) - return ret; - - gl_extensions = (const char *)glGetString(GL_EXTENSIONS); - - if (!HasExtension("GL_OES_EGL_image", gl_extensions)) - ALOGW("GL_OES_EGL_image extension not supported"); - - if (!HasExtension("GL_OES_EGL_image_external", gl_extensions)) - ALOGW("GL_OES_EGL_image_external extension not supported"); - - GLuint vertex_buffer; - glGenBuffers(1, &vertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - vertex_buffer_.reset(vertex_buffer); - - 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; - } - - return 0; -} - -GLWorkerCompositor::~GLWorkerCompositor() { - if (egl_display_ != EGL_NO_DISPLAY && egl_ctx_ != EGL_NO_CONTEXT) - if (eglDestroyContext(egl_display_, egl_ctx_) == EGL_FALSE) - ALOGE("Failed to destroy OpenGL ES Context: %s", GetEGLError()); -} - -int GLWorkerCompositor::Composite(DrmHwcLayer *layers, - DrmCompositionRegion *regions, - size_t num_regions, - const sp &framebuffer, - Importer *importer) { - ATRACE_CALL(); - int ret = 0; - std::vector layer_textures; - std::vector commands; - - if (num_regions == 0) { - 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; - } - - std::unordered_set layers_used_indices; - for (size_t region_index = 0; region_index < num_regions; region_index++) { - DrmCompositionRegion ®ion = regions[region_index]; - layers_used_indices.insert(region.source_layers.begin(), - region.source_layers.end()); - commands.emplace_back(); - ConstructCommand(layers, region, commands.back()); - } - - for (size_t layer_index = 0; layer_index < MAX_OVERLAPPING_LAYERS; - layer_index++) { - DrmHwcLayer *layer = &layers[layer_index]; - - layer_textures.emplace_back(); - - if (layers_used_indices.count(layer_index) == 0) - continue; - - ret = CreateTextureFromHandle(egl_display_, layer->get_usable_handle(), - importer, &layer_textures.back()); - - if (!ret) { - ret = EGLFenceWait(egl_display_, layer->acquire_fence.Release()); - } - if (ret) { - layer_textures.pop_back(); - ret = -EINVAL; - } - } - - if (ret) { - EndContext(); - return ret; - } - - glViewport(0, 0, frame_width, frame_height); - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_.get()); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, NULL); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, - (void *)(sizeof(float) * 2)); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glEnable(GL_SCISSOR_TEST); - - for (const RenderingCommand &cmd : commands) { - if (cmd.texture_count == 0) - continue; - - // TODO(zachr): handle the case of too many overlapping textures for one - // area by falling back to rendering as many layers as possible using - // multiple blending passes. - GLint program = PrepareAndCacheProgram(cmd.texture_count); - if (program == 0) { - ALOGE("Too many layers to render in one area"); - continue; - } - - glUseProgram(program); - GLint gl_viewport_loc = glGetUniformLocation(program, "uViewport"); - GLint gl_crop_loc = glGetUniformLocation(program, "uLayerCrop"); - GLint gl_alpha_loc = glGetUniformLocation(program, "uLayerAlpha"); - GLint gl_premult_loc = glGetUniformLocation(program, "uLayerPremult"); - GLint gl_tex_matrix_loc = glGetUniformLocation(program, "uTexMatrix"); - glUniform4f(gl_viewport_loc, cmd.bounds[0] / (float)frame_width, - cmd.bounds[1] / (float)frame_height, - (cmd.bounds[2] - cmd.bounds[0]) / (float)frame_width, - (cmd.bounds[3] - cmd.bounds[1]) / (float)frame_height); - - for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) { - std::ostringstream texture_name_formatter; - texture_name_formatter << "uLayerTexture" << src_index; - GLint gl_tex_loc = - glGetUniformLocation(program, texture_name_formatter.str().c_str()); - - const RenderingCommand::TextureSource &src = cmd.textures[src_index]; - glUniform1f(gl_alpha_loc + src_index, src.alpha); - glUniform1f(gl_premult_loc + src_index, src.premult); - glUniform4f(gl_crop_loc + src_index, src.crop_bounds[0], - src.crop_bounds[1], src.crop_bounds[2] - src.crop_bounds[0], - src.crop_bounds[3] - src.crop_bounds[1]); - glUniform1i(gl_tex_loc, src_index); - glUniformMatrix2fv(gl_tex_matrix_loc + src_index, 1, GL_FALSE, - src.texture_matrix); - glActiveTexture(GL_TEXTURE0 + src_index); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, - layer_textures[src.texture_index].texture.get()); - } - - glScissor(cmd.bounds[0], cmd.bounds[1], cmd.bounds[2] - cmd.bounds[0], - cmd.bounds[3] - cmd.bounds[1]); - glDrawArrays(GL_TRIANGLES, 0, 3); - - for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) { - glActiveTexture(GL_TEXTURE0 + src_index); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); - } - } - - glDisable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glUseProgram(0); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - EndContext(); - return ret; -} - -void GLWorkerCompositor::Finish() { - ATRACE_CALL(); - glFinish(); - - char use_framebuffer_cache_opt[PROPERTY_VALUE_MAX]; - property_get("hwc.drm.use_framebuffer_cache", use_framebuffer_cache_opt, "1"); - bool use_framebuffer_cache = atoi(use_framebuffer_cache_opt); - - if (use_framebuffer_cache) { - for (auto &fb : cached_framebuffers_) - fb.strong_framebuffer.clear(); - } else { - cached_framebuffers_.clear(); - } -} - -GLWorkerCompositor::CachedFramebuffer::CachedFramebuffer( - const sp &gb, AutoEGLDisplayImage &&image, - AutoGLTexture &&tex, AutoGLFramebuffer &&fb) - : strong_framebuffer(gb), - weak_framebuffer(gb), - egl_fb_image(std::move(image)), - gl_fb_tex(std::move(tex)), - gl_fb(std::move(fb)) { -} - -bool GLWorkerCompositor::CachedFramebuffer::Promote() { - if (strong_framebuffer.get() != NULL) - return true; - strong_framebuffer = weak_framebuffer.promote(); - return strong_framebuffer.get() != NULL; -} - -GLWorkerCompositor::CachedFramebuffer * -GLWorkerCompositor::FindCachedFramebuffer( - const sp &framebuffer) { - for (auto &fb : cached_framebuffers_) - if (fb.weak_framebuffer == framebuffer) - return &fb; - return NULL; -} - -GLWorkerCompositor::CachedFramebuffer * -GLWorkerCompositor::PrepareAndCacheFramebuffer( - const sp &framebuffer) { - CachedFramebuffer *cached_framebuffer = FindCachedFramebuffer(framebuffer); - if (cached_framebuffer != NULL) { - if (cached_framebuffer->Promote()) { - glBindFramebuffer(GL_FRAMEBUFFER, cached_framebuffer->gl_fb.get()); - return cached_framebuffer; - } - - for (auto it = cached_framebuffers_.begin(); - it != cached_framebuffers_.end(); ++it) { - if (it->weak_framebuffer == framebuffer) { - cached_framebuffers_.erase(it); - break; - } - } - } - - AutoEGLDisplayImage egl_fb_image( - egl_display_, - eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - (EGLClientBuffer)framebuffer->getNativeBuffer(), - NULL /* no attribs */)); - - if (egl_fb_image.image() == EGL_NO_IMAGE_KHR) { - ALOGE("Failed to make image from target buffer: %s", GetEGLError()); - return NULL; - } - - GLuint gl_fb_tex; - glGenTextures(1, &gl_fb_tex); - AutoGLTexture gl_fb_tex_auto(gl_fb_tex); - glBindTexture(GL_TEXTURE_2D, gl_fb_tex); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, - (GLeglImageOES)egl_fb_image.image()); - glBindTexture(GL_TEXTURE_2D, 0); - - GLuint gl_fb; - glGenFramebuffers(1, &gl_fb); - AutoGLFramebuffer gl_fb_auto(gl_fb); - glBindFramebuffer(GL_FRAMEBUFFER, gl_fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - gl_fb_tex, 0); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - ALOGE("Failed framebuffer check for created target buffer: %s", - GetGLFramebufferError()); - return NULL; - } - - cached_framebuffers_.emplace_back(framebuffer, std::move(egl_fb_image), - std::move(gl_fb_tex_auto), - std::move(gl_fb_auto)); - return &cached_framebuffers_.back(); -} - -GLint GLWorkerCompositor::PrepareAndCacheProgram(unsigned texture_count) { - if (blend_programs_.size() >= texture_count) { - GLint program = blend_programs_[texture_count - 1].get(); - if (program != 0) - return program; - } - - AutoGLProgram program = GenerateProgram(texture_count, NULL); - if (program.get() != 0) { - if (blend_programs_.size() < texture_count) - blend_programs_.resize(texture_count); - blend_programs_[texture_count - 1] = std::move(program); - return blend_programs_[texture_count - 1].get(); - } - - return 0; -} - -} // namespace android diff --git a/glworker.h b/glworker.h deleted file mode 100644 index 26de55d725cd..000000000000 --- a/glworker.h +++ /dev/null @@ -1,94 +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_GL_WORKER_H_ -#define ANDROID_GL_WORKER_H_ - -#include - -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES - -#include -#include -#include -#include - -#include - -#include "autogl.h" - -namespace android { - -struct DrmHwcLayer; -struct DrmCompositionRegion; - -class GLWorkerCompositor { - public: - GLWorkerCompositor(); - ~GLWorkerCompositor(); - - int Init(); - int Composite(DrmHwcLayer *layers, DrmCompositionRegion *regions, - size_t num_regions, const sp &framebuffer, - Importer *importer); - void Finish(); - - private: - struct CachedFramebuffer { - // If the strong_framebuffer is non-NULL, we are holding a strong reference - // until we are sure rendering is done. The weak reference will be equal in - // that case. - sp strong_framebuffer; - wp weak_framebuffer; - AutoEGLDisplayImage egl_fb_image; - AutoGLTexture gl_fb_tex; - AutoGLFramebuffer gl_fb; - - CachedFramebuffer(const sp &gb, AutoEGLDisplayImage &&image, - AutoGLTexture &&tex, AutoGLFramebuffer &&fb); - - 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( - const sp &framebuffer); - - GLint PrepareAndCacheProgram(unsigned texture_count); - - EGLDisplay egl_display_; - EGLContext egl_ctx_; - - std::vector blend_programs_; - AutoGLBuffer vertex_buffer_; - - std::vector cached_framebuffers_; -}; -} - -#endif diff --git a/hwcomposer.cpp b/hwcomposer.cpp deleted file mode 100644 index 338e042895a9..000000000000 --- a/hwcomposer.cpp +++ /dev/null @@ -1,841 +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 ATRACE_TAG ATRACE_TAG_GRAPHICS -#define LOG_TAG "hwcomposer-drm" - -#include "drmhwcomposer.h" -#include "drmeventlistener.h" -#include "drmresources.h" -#include "platform.h" -#include "virtualcompositorworker.h" -#include "vsyncworker.h" - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define UM_PER_INCH 25400 - -namespace android { - -class DummySwSyncTimeline { - public: - int Init() { - int ret = timeline_fd_.Set(sw_sync_timeline_create()); - if (ret < 0) - return ret; - return 0; - } - - UniqueFd CreateDummyFence() { - int ret = sw_sync_fence_create(timeline_fd_.get(), "dummy fence", - timeline_pt_ + 1); - if (ret < 0) { - ALOGE("Failed to create dummy fence %d", ret); - return ret; - } - - UniqueFd ret_fd(ret); - - ret = sw_sync_timeline_inc(timeline_fd_.get(), 1); - if (ret) { - ALOGE("Failed to increment dummy sync timeline %d", ret); - return ret; - } - - ++timeline_pt_; - return ret_fd; - } - - private: - UniqueFd timeline_fd_; - int timeline_pt_ = 0; -}; - -struct CheckedOutputFd { - CheckedOutputFd(int *fd, const char *description, - DummySwSyncTimeline &timeline) - : fd_(fd), description_(description), timeline_(timeline) { - } - CheckedOutputFd(CheckedOutputFd &&rhs) - : description_(rhs.description_), timeline_(rhs.timeline_) { - std::swap(fd_, rhs.fd_); - } - - CheckedOutputFd &operator=(const CheckedOutputFd &rhs) = delete; - - ~CheckedOutputFd() { - if (fd_ == NULL) - return; - - if (*fd_ >= 0) - return; - - *fd_ = timeline_.CreateDummyFence().Release(); - - if (*fd_ < 0) - ALOGE("Failed to fill %s (%p == %d) before destruction", - description_.c_str(), fd_, *fd_); - } - - private: - int *fd_ = NULL; - std::string description_; - DummySwSyncTimeline &timeline_; -}; - -typedef struct hwc_drm_display { - struct hwc_context_t *ctx; - int display; - - std::vector config_ids; - - VSyncWorker vsync_worker; -} hwc_drm_display_t; - -class DrmHotplugHandler : public DrmEventHandler { - public: - void Init(DrmResources *drm, const struct hwc_procs *procs) { - drm_ = drm; - procs_ = procs; - } - - void HandleEvent(uint64_t timestamp_us) { - for (auto &conn : drm_->connectors()) { - drmModeConnection old_state = conn->state(); - - conn->UpdateModes(); - - drmModeConnection cur_state = conn->state(); - - if (cur_state == old_state) - continue; - - ALOGI("%s event @%" PRIu64 " for connector %u\n", - cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us, - conn->id()); - - if (cur_state == DRM_MODE_CONNECTED) { - // Take the first one, then look for the preferred - DrmMode mode = *(conn->modes().begin()); - for (auto &m : conn->modes()) { - if (m.type() & DRM_MODE_TYPE_PREFERRED) { - mode = m; - break; - } - } - ALOGI("Setting mode %dx%d for connector %d\n", mode.h_display(), - mode.v_display(), conn->id()); - int ret = drm_->SetDisplayActiveMode(conn->display(), mode); - if (ret) { - ALOGE("Failed to set active config %d", ret); - return; - } - } else { - int ret = drm_->SetDpmsMode(conn->display(), DRM_MODE_DPMS_OFF); - if (ret) { - ALOGE("Failed to set dpms mode off %d", ret); - return; - } - } - - procs_->hotplug(procs_, conn->display(), - cur_state == DRM_MODE_CONNECTED ? 1 : 0); - } - } - - private: - DrmResources *drm_ = NULL; - const struct hwc_procs *procs_ = NULL; -}; - -struct hwc_context_t { - // map of display:hwc_drm_display_t - typedef std::map DisplayMap; - - ~hwc_context_t() { - virtual_compositor_worker.Exit(); - } - - hwc_composer_device_1_t device; - hwc_procs_t const *procs = NULL; - - DisplayMap displays; - DrmResources drm; - std::unique_ptr importer; - const gralloc_module_t *gralloc; - DummySwSyncTimeline dummy_timeline; - VirtualCompositorWorker virtual_compositor_worker; - DrmHotplugHandler hotplug_handler; -}; - -class DrmVsyncCallback : public VsyncCallback { - public: - DrmVsyncCallback(hwc_procs_t const *procs) : procs_(procs) { - } - - void Callback(int display, int64_t timestamp) { - procs_->vsync(procs_, display, timestamp); - } - private: - hwc_procs_t const *procs_; -}; - -static void hwc_dump(struct hwc_composer_device_1 *dev, char *buff, - int buff_len) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - std::ostringstream out; - - ctx->drm.compositor()->Dump(&out); - std::string out_str = out.str(); - strncpy(buff, out_str.c_str(), - std::min((size_t)buff_len, out_str.length() + 1)); - buff[buff_len - 1] = '\0'; -} - -static bool hwc_skip_layer(const std::pair &indices, int i) { - return indices.first >= 0 && i >= indices.first && i <= indices.second; -} - -static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays, - hwc_display_contents_1_t **display_contents) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - - for (int i = 0; i < (int)num_displays; ++i) { - if (!display_contents[i]) - continue; - - bool use_framebuffer_target = false; - DrmMode mode; - if (i == HWC_DISPLAY_VIRTUAL) { - use_framebuffer_target = true; - } else { - DrmConnector *c = ctx->drm.GetConnectorForDisplay(i); - if (!c) { - ALOGE("Failed to get DrmConnector for display %d", i); - return -ENODEV; - } - mode = c->active_mode(); - } - - // Since we can't composite HWC_SKIP_LAYERs by ourselves, we'll let SF - // handle all layers in between the first and last skip layers. So find the - // outer indices and mark everything in between as HWC_FRAMEBUFFER - std::pair skip_layer_indices(-1, -1); - int num_layers = display_contents[i]->numHwLayers; - for (int j = 0; !use_framebuffer_target && j < num_layers; ++j) { - hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j]; - - if (!(layer->flags & HWC_SKIP_LAYER)) - continue; - - if (skip_layer_indices.first == -1) - skip_layer_indices.first = j; - skip_layer_indices.second = j; - } - - for (int j = 0; j < num_layers; ++j) { - hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j]; - - if (!use_framebuffer_target && !hwc_skip_layer(skip_layer_indices, j)) { - // If the layer is off the screen, don't earmark it for an overlay. - // We'll leave it as-is, which effectively just drops it from the frame - const hwc_rect_t *frame = &layer->displayFrame; - if ((frame->right - frame->left) <= 0 || - (frame->bottom - frame->top) <= 0 || - frame->right <= 0 || frame->bottom <= 0 || - frame->left >= (int)mode.h_display() || - frame->top >= (int)mode.v_display()) - continue; - - if (layer->compositionType == HWC_FRAMEBUFFER) - layer->compositionType = HWC_OVERLAY; - } else { - switch (layer->compositionType) { - case HWC_OVERLAY: - case HWC_BACKGROUND: - case HWC_SIDEBAND: - case HWC_CURSOR_OVERLAY: - layer->compositionType = HWC_FRAMEBUFFER; - break; - } - } - } - } - - return 0; -} - -static void hwc_add_layer_to_retire_fence( - hwc_layer_1_t *layer, hwc_display_contents_1_t *display_contents) { - if (layer->releaseFenceFd < 0) - return; - - if (display_contents->retireFenceFd >= 0) { - int old_retire_fence = display_contents->retireFenceFd; - display_contents->retireFenceFd = - sync_merge("dc_retire", old_retire_fence, layer->releaseFenceFd); - close(old_retire_fence); - } else { - display_contents->retireFenceFd = dup(layer->releaseFenceFd); - } -} - -static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays, - hwc_display_contents_1_t **sf_display_contents) { - ATRACE_CALL(); - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - int ret = 0; - - std::vector checked_output_fences; - std::vector displays_contents; - std::vector layers_map; - std::vector> layers_indices; - displays_contents.reserve(num_displays); - // layers_map.reserve(num_displays); - layers_indices.reserve(num_displays); - - // Phase one does nothing that would cause errors. Only take ownership of FDs. - for (size_t i = 0; i < num_displays; ++i) { - hwc_display_contents_1_t *dc = sf_display_contents[i]; - displays_contents.emplace_back(); - DrmHwcDisplayContents &display_contents = displays_contents.back(); - layers_indices.emplace_back(); - std::vector &indices_to_composite = layers_indices.back(); - - if (!sf_display_contents[i]) - continue; - - if (i == HWC_DISPLAY_VIRTUAL) { - ctx->virtual_compositor_worker.QueueComposite(dc); - continue; - } - - std::ostringstream display_index_formatter; - display_index_formatter << "retire fence for display " << i; - std::string display_fence_description(display_index_formatter.str()); - checked_output_fences.emplace_back(&dc->retireFenceFd, - display_fence_description.c_str(), - ctx->dummy_timeline); - display_contents.retire_fence = OutputFd(&dc->retireFenceFd); - - size_t num_dc_layers = dc->numHwLayers; - int framebuffer_target_index = -1; - for (size_t j = 0; j < num_dc_layers; ++j) { - hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; - if (sf_layer->compositionType == HWC_FRAMEBUFFER_TARGET) { - framebuffer_target_index = j; - break; - } - } - - for (size_t j = 0; j < num_dc_layers; ++j) { - hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; - - display_contents.layers.emplace_back(); - DrmHwcLayer &layer = display_contents.layers.back(); - - // In prepare() we marked all layers FRAMEBUFFER between SKIP_LAYER's. - // This means we should insert the FB_TARGET layer in the composition - // stack at the location of the first skip layer, and ignore the rest. - if (sf_layer->flags & HWC_SKIP_LAYER) { - if (framebuffer_target_index < 0) - continue; - int idx = framebuffer_target_index; - framebuffer_target_index = -1; - hwc_layer_1_t *fbt_layer = &dc->hwLayers[idx]; - if (!fbt_layer->handle || (fbt_layer->flags & HWC_SKIP_LAYER)) { - ALOGE("Invalid HWC_FRAMEBUFFER_TARGET with HWC_SKIP_LAYER present"); - continue; - } - indices_to_composite.push_back(idx); - continue; - } - - if (sf_layer->compositionType == HWC_OVERLAY) - indices_to_composite.push_back(j); - - layer.acquire_fence.Set(sf_layer->acquireFenceFd); - sf_layer->acquireFenceFd = -1; - - std::ostringstream layer_fence_formatter; - layer_fence_formatter << "release fence for layer " << j << " of display " - << i; - std::string layer_fence_description(layer_fence_formatter.str()); - checked_output_fences.emplace_back(&sf_layer->releaseFenceFd, - layer_fence_description.c_str(), - ctx->dummy_timeline); - layer.release_fence = OutputFd(&sf_layer->releaseFenceFd); - } - - // This is a catch-all in case we get a frame without any overlay layers, or - // skip layers, but with a value fb_target layer. This _shouldn't_ happen, - // but it's not ruled out by the hwc specification - if (indices_to_composite.empty() && framebuffer_target_index >= 0) { - hwc_layer_1_t *sf_layer = &dc->hwLayers[framebuffer_target_index]; - if (!sf_layer->handle || (sf_layer->flags & HWC_SKIP_LAYER)) { - ALOGE( - "Expected valid layer with HWC_FRAMEBUFFER_TARGET when all " - "HWC_OVERLAY layers are skipped."); - ret = -EINVAL; - } - indices_to_composite.push_back(framebuffer_target_index); - } - } - - if (ret) - return ret; - - for (size_t i = 0; i < num_displays; ++i) { - hwc_display_contents_1_t *dc = sf_display_contents[i]; - DrmHwcDisplayContents &display_contents = displays_contents[i]; - if (!sf_display_contents[i] || i == HWC_DISPLAY_VIRTUAL) - continue; - - layers_map.emplace_back(); - DrmCompositionDisplayLayersMap &map = layers_map.back(); - map.display = i; - map.geometry_changed = - (dc->flags & HWC_GEOMETRY_CHANGED) == HWC_GEOMETRY_CHANGED; - std::vector &indices_to_composite = layers_indices[i]; - for (size_t j : indices_to_composite) { - hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; - - DrmHwcLayer &layer = display_contents.layers[j]; - - ret = layer.InitFromHwcLayer(sf_layer, ctx->importer.get(), ctx->gralloc); - if (ret) { - ALOGE("Failed to init composition from layer %d", ret); - return ret; - } - map.layers.emplace_back(std::move(layer)); - } - } - - std::unique_ptr composition( - ctx->drm.compositor()->CreateComposition(ctx->importer.get())); - if (!composition) { - ALOGE("Drm composition init failed"); - return -EINVAL; - } - - ret = composition->SetLayers(layers_map.size(), layers_map.data()); - if (ret) { - return -EINVAL; - } - - ret = ctx->drm.compositor()->QueueComposition(std::move(composition)); - if (ret) { - return -EINVAL; - } - - for (size_t i = 0; i < num_displays; ++i) { - hwc_display_contents_1_t *dc = sf_display_contents[i]; - if (!dc) - continue; - - size_t num_dc_layers = dc->numHwLayers; - for (size_t j = 0; j < num_dc_layers; ++j) { - hwc_layer_1_t *layer = &dc->hwLayers[j]; - if (layer->flags & HWC_SKIP_LAYER) - continue; - hwc_add_layer_to_retire_fence(layer, dc); - } - } - - composition.reset(NULL); - - return ret; -} - -static int hwc_event_control(struct hwc_composer_device_1 *dev, int display, - int event, int enabled) { - if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1)) - return -EINVAL; - - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - hwc_drm_display_t *hd = &ctx->displays[display]; - hd->vsync_worker.VSyncControl(enabled); - return 0; -} - -static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display, - int mode) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - - uint64_t dpmsValue = 0; - switch (mode) { - case HWC_POWER_MODE_OFF: - dpmsValue = DRM_MODE_DPMS_OFF; - break; - - /* We can't support dozing right now, so go full on */ - case HWC_POWER_MODE_DOZE: - case HWC_POWER_MODE_DOZE_SUSPEND: - case HWC_POWER_MODE_NORMAL: - dpmsValue = DRM_MODE_DPMS_ON; - break; - }; - return ctx->drm.SetDpmsMode(display, dpmsValue); -} - -static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what, - int *value) { - switch (what) { - case HWC_BACKGROUND_LAYER_SUPPORTED: - *value = 0; /* TODO: We should do this */ - break; - case HWC_VSYNC_PERIOD: - ALOGW("Query for deprecated vsync value, returning 60Hz"); - *value = 1000 * 1000 * 1000 / 60; - break; - case HWC_DISPLAY_TYPES_SUPPORTED: - *value = HWC_DISPLAY_PRIMARY_BIT | HWC_DISPLAY_EXTERNAL_BIT | - HWC_DISPLAY_VIRTUAL_BIT; - break; - } - return 0; -} - -static void hwc_register_procs(struct hwc_composer_device_1 *dev, - hwc_procs_t const *procs) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - - ctx->procs = procs; - - for (std::pair &display_entry : ctx->displays) { - auto callback = std::make_shared(procs); - display_entry.second.vsync_worker.RegisterCallback(std::move(callback)); - } - - ctx->hotplug_handler.Init(&ctx->drm, procs); - ctx->drm.event_listener()->RegisterHotplugHandler(&ctx->hotplug_handler); -} - -static int hwc_get_display_configs(struct hwc_composer_device_1 *dev, - int display, uint32_t *configs, - size_t *num_configs) { - if (!*num_configs) - return 0; - - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - hwc_drm_display_t *hd = &ctx->displays[display]; - hd->config_ids.clear(); - - DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display); - if (!connector) { - ALOGE("Failed to get connector for display %d", display); - return -ENODEV; - } - - int ret = connector->UpdateModes(); - if (ret) { - ALOGE("Failed to update display modes %d", ret); - return ret; - } - - for (const DrmMode &mode : connector->modes()) { - size_t idx = hd->config_ids.size(); - if (idx == *num_configs) - break; - hd->config_ids.push_back(mode.id()); - configs[idx] = mode.id(); - } - *num_configs = hd->config_ids.size(); - return *num_configs == 0 ? -1 : 0; -} - -static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev, - int display, uint32_t config, - const uint32_t *attributes, - int32_t *values) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - DrmConnector *c = ctx->drm.GetConnectorForDisplay(display); - if (!c) { - ALOGE("Failed to get DrmConnector for display %d", display); - return -ENODEV; - } - DrmMode mode; - for (const DrmMode &conn_mode : c->modes()) { - if (conn_mode.id() == config) { - mode = conn_mode; - break; - } - } - if (mode.id() == 0) { - ALOGE("Failed to find active mode for display %d", display); - return -ENOENT; - } - - uint32_t mm_width = c->mm_width(); - uint32_t mm_height = c->mm_height(); - for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) { - switch (attributes[i]) { - case HWC_DISPLAY_VSYNC_PERIOD: - values[i] = 1000 * 1000 * 1000 / mode.v_refresh(); - break; - case HWC_DISPLAY_WIDTH: - values[i] = mode.h_display(); - break; - case HWC_DISPLAY_HEIGHT: - values[i] = mode.v_display(); - break; - case HWC_DISPLAY_DPI_X: - /* Dots per 1000 inches */ - values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0; - break; - case HWC_DISPLAY_DPI_Y: - /* Dots per 1000 inches */ - values[i] = - mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0; - break; - } - } - return 0; -} - -static int hwc_get_active_config(struct hwc_composer_device_1 *dev, - int display) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - DrmConnector *c = ctx->drm.GetConnectorForDisplay(display); - if (!c) { - ALOGE("Failed to get DrmConnector for display %d", display); - return -ENODEV; - } - - DrmMode mode = c->active_mode(); - hwc_drm_display_t *hd = &ctx->displays[display]; - for (size_t i = 0; i < hd->config_ids.size(); ++i) { - if (hd->config_ids[i] == mode.id()) - return i; - } - return -1; -} - -static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display, - int index) { - struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; - hwc_drm_display_t *hd = &ctx->displays[display]; - if (index >= (int)hd->config_ids.size()) { - ALOGE("Invalid config index %d passed in", index); - return -EINVAL; - } - - DrmConnector *c = ctx->drm.GetConnectorForDisplay(display); - if (!c) { - ALOGE("Failed to get connector for display %d", display); - return -ENODEV; - } - - if (c->state() != DRM_MODE_CONNECTED) - return -ENODEV; - - DrmMode mode; - for (const DrmMode &conn_mode : c->modes()) { - if (conn_mode.id() == hd->config_ids[index]) { - mode = conn_mode; - break; - } - } - if (mode.id() != hd->config_ids[index]) { - ALOGE("Could not find active mode for %d/%d", index, hd->config_ids[index]); - return -ENOENT; - } - int ret = ctx->drm.SetDisplayActiveMode(display, mode); - if (ret) { - ALOGE("Failed to set active config %d", ret); - return ret; - } - ret = ctx->drm.SetDpmsMode(display, DRM_MODE_DPMS_ON); - if (ret) { - ALOGE("Failed to set dpms mode on %d", ret); - return ret; - } - return ret; -} - -static int hwc_device_close(struct hw_device_t *dev) { - struct hwc_context_t *ctx = (struct hwc_context_t *)dev; - delete ctx; - return 0; -} - -/* - * TODO: This function sets the active config to the first one in the list. This - * should be fixed such that it selects the preferred mode for the display, or - * some other, saner, method of choosing the config. - */ -static int hwc_set_initial_config(hwc_drm_display_t *hd) { - uint32_t config; - size_t num_configs = 1; - int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config, - &num_configs); - if (ret || !num_configs) - return 0; - - ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0); - if (ret) { - ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret); - return ret; - } - - return ret; -} - -static int hwc_initialize_display(struct hwc_context_t *ctx, int display) { - hwc_drm_display_t *hd = &ctx->displays[display]; - hd->ctx = ctx; - hd->display = display; - - int ret = hwc_set_initial_config(hd); - if (ret) { - ALOGE("Failed to set initial config for d=%d ret=%d", display, ret); - return ret; - } - - ret = hd->vsync_worker.Init(&ctx->drm, display); - if (ret) { - ALOGE("Failed to create event worker for display %d %d\n", display, ret); - return ret; - } - - return 0; -} - -static int hwc_enumerate_displays(struct hwc_context_t *ctx) { - int ret; - for (auto &conn : ctx->drm.connectors()) { - ret = hwc_initialize_display(ctx, conn->display()); - if (ret) { - ALOGE("Failed to initialize display %d", conn->display()); - return ret; - } - } - - ret = ctx->virtual_compositor_worker.Init(); - if (ret) { - ALOGE("Failed to initialize virtual compositor worker"); - return ret; - } - return 0; -} - -static int hwc_device_open(const struct hw_module_t *module, const char *name, - struct hw_device_t **dev) { - if (strcmp(name, HWC_HARDWARE_COMPOSER)) { - ALOGE("Invalid module name- %s", name); - return -EINVAL; - } - - std::unique_ptr ctx(new hwc_context_t()); - if (!ctx) { - ALOGE("Failed to allocate hwc context"); - return -ENOMEM; - } - - int ret = ctx->drm.Init(); - if (ret) { - ALOGE("Can't initialize Drm object %d", ret); - return ret; - } - - ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, - (const hw_module_t **)&ctx->gralloc); - if (ret) { - ALOGE("Failed to open gralloc module %d", ret); - return ret; - } - - ret = ctx->dummy_timeline.Init(); - if (ret) { - ALOGE("Failed to create dummy sw sync timeline %d", ret); - return ret; - } - - ctx->importer.reset(Importer::CreateInstance(&ctx->drm)); - if (!ctx->importer) { - ALOGE("Failed to create importer instance"); - return ret; - } - - ret = hwc_enumerate_displays(ctx.get()); - if (ret) { - ALOGE("Failed to enumerate displays: %s", strerror(ret)); - return ret; - } - - ctx->device.common.tag = HARDWARE_DEVICE_TAG; - ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4; - ctx->device.common.module = const_cast(module); - ctx->device.common.close = hwc_device_close; - - ctx->device.dump = hwc_dump; - ctx->device.prepare = hwc_prepare; - ctx->device.set = hwc_set; - ctx->device.eventControl = hwc_event_control; - ctx->device.setPowerMode = hwc_set_power_mode; - ctx->device.query = hwc_query; - ctx->device.registerProcs = hwc_register_procs; - ctx->device.getDisplayConfigs = hwc_get_display_configs; - ctx->device.getDisplayAttributes = hwc_get_display_attributes; - ctx->device.getActiveConfig = hwc_get_active_config; - ctx->device.setActiveConfig = hwc_set_active_config; - ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */ - - *dev = &ctx->device.common; - ctx.release(); - - return 0; -} -} - -static struct hw_module_methods_t hwc_module_methods = { - .open = android::hwc_device_open -}; - -hwc_module_t HAL_MODULE_INFO_SYM = { - .common = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 1, - .version_minor = 0, - .id = HWC_HARDWARE_MODULE_ID, - .name = "DRM hwcomposer module", - .author = "The Android Open Source Project", - .methods = &hwc_module_methods, - .dso = NULL, - .reserved = {0}, - } -}; diff --git a/platform.cpp b/platform.cpp index 62b03a881dca..b6c39d05a3a1 100644 --- a/platform.cpp +++ b/platform.cpp @@ -37,7 +37,7 @@ std::vector Planner::GetUsablePlanes( } std::tuple> Planner::ProvisionPlanes( - std::map &layers, bool use_squash_fb, DrmCrtc *crtc, + std::map &layers, DrmCrtc *crtc, std::vector *primary_planes, std::vector *overlay_planes) { std::vector composition; @@ -48,30 +48,6 @@ std::tuple> Planner::ProvisionPlanes( return std::make_tuple(-ENODEV, std::vector()); } - // If needed, reserve the squash plane at the highest z-order - DrmPlane *squash_plane = NULL; - if (use_squash_fb) { - if (!planes.empty()) { - squash_plane = planes.back(); - planes.pop_back(); - } else { - ALOGI("Not enough planes to reserve for squash fb"); - } - } - - // If needed, reserve the precomp plane at the next highest z-order - DrmPlane *precomp_plane = NULL; - if (layers.size() > planes.size()) { - if (!planes.empty()) { - precomp_plane = planes.back(); - planes.pop_back(); - composition.emplace_back(DrmCompositionPlane::Type::kPrecomp, - precomp_plane, crtc); - } else { - ALOGE("Not enough planes to reserve for precomp fb"); - } - } - // Go through the provisioning stages and provision planes for (auto &i : stages_) { int ret = i->ProvisionPlanes(&composition, layers, crtc, &planes); @@ -81,10 +57,6 @@ std::tuple> Planner::ProvisionPlanes( } } - if (squash_plane) - composition.emplace_back(DrmCompositionPlane::Type::kSquash, squash_plane, - crtc); - return std::make_tuple(0, std::move(composition)); } @@ -109,62 +81,6 @@ int PlanStageProtected::ProvisionPlanes( i = layers.erase(i); } - if (protected_zorder == -1) - return 0; - - // Add any layers below the protected content to the precomposition since we - // need to punch a hole through them. - for (auto i = layers.begin(); i != layers.end();) { - // Skip layers above the z-order of the protected content - if (i->first > static_cast(protected_zorder)) { - ++i; - continue; - } - - // If there's no precomp layer already queued, queue one now. - DrmCompositionPlane *precomp = GetPrecomp(composition); - if (precomp) { - precomp->source_layers().emplace_back(i->first); - } else { - if (!planes->empty()) { - DrmPlane *precomp_plane = planes->back(); - planes->pop_back(); - composition->emplace_back(DrmCompositionPlane::Type::kPrecomp, - precomp_plane, crtc, i->first); - } else { - ALOGE("Not enough planes to reserve for precomp fb"); - } - } - i = layers.erase(i); - } - return 0; -} - -int PlanStagePrecomp::ProvisionPlanes( - std::vector *composition, - std::map &layers, DrmCrtc * /*crtc*/, - std::vector * /*planes*/) { - DrmCompositionPlane *precomp = GetPrecomp(composition); - if (!precomp || precomp->source_layers().empty()) - return 0; - - // Find lowest zorder out of precomp layers - size_t precomp_zorder = *std::min_element( - precomp->source_layers().begin(), precomp->source_layers().end(), - [](size_t a, size_t b) { return a < b; }); - - // if there are any remaining layers on top of any of the precomp layers, - // add them to precomp to avoid blending issues since precomp is always at - // highest zorder - for (auto i = layers.begin(); i != layers.end();) { - if (i->first < precomp_zorder) { - i++; - continue; - } - precomp->source_layers().emplace_back(i->first); - i = layers.erase(i); - } - return 0; } @@ -183,13 +99,6 @@ int PlanStageGreedy::ProvisionPlanes( ALOGE("Failed to emplace layer %zu, dropping it", i->first); } - // Put the rest of the layers in the precomp plane - DrmCompositionPlane *precomp = GetPrecomp(composition); - if (precomp) { - for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) - precomp->source_layers().emplace_back(i->first); - } - return 0; } } diff --git a/platform.h b/platform.h index e417bf785a2c..639ac884ba3f 100644 --- a/platform.h +++ b/platform.h @@ -38,10 +38,6 @@ class Importer { // Creates a platform-specific importer instance static Importer *CreateInstance(DrmResources *drm); - // Imports EGLImage for glcompositor, since NV handles this in non-standard - // way, and fishing out the details is specific to the gralloc used. - virtual EGLImageKHR ImportImage(EGLDisplay egl_display, buffer_handle_t handle) = 0; - // Imports the buffer referred to by handle into bo. // // Note: This can be called from a different thread than ReleaseBuffer. The @@ -77,17 +73,7 @@ class Planner { return plane; } - // Finds and returns the squash layer from the composition - static DrmCompositionPlane *GetPrecomp( - std::vector *composition) { - auto l = GetPrecompIter(composition); - if (l == composition->end()) - return NULL; - return &(*l); - } - - // Inserts the given layer:plane in the composition right before the precomp - // layer + // Inserts the given layer:plane in the composition at the back static int Emplace(std::vector *composition, std::vector *planes, DrmCompositionPlane::Type type, DrmCrtc *crtc, @@ -96,40 +82,25 @@ class Planner { if (!plane) return -ENOENT; - auto precomp = GetPrecompIter(composition); - composition->emplace(precomp, type, plane, crtc, source_layer); + composition->emplace_back(type, plane, crtc, source_layer); return 0; } - - private: - static std::vector::iterator GetPrecompIter( - std::vector *composition) { - return std::find_if(composition->begin(), composition->end(), - [](const DrmCompositionPlane &p) { - return p.type() == DrmCompositionPlane::Type::kPrecomp; - }); - } }; // Creates a planner instance with platform-specific planning stages static std::unique_ptr CreateInstance(DrmResources *drm); // Takes a stack of layers and provisions hardware planes for them. If the - // entire stack can't fit in hardware, the Planner may place the remaining - // layers in a PRECOMP plane. Layers in the PRECOMP plane will be composited - // using GL. PRECOMP planes should be placed above any 1:1 layer:plane - // compositions. If use_squash_fb is true, the Planner should try to reserve a - // plane at the highest z-order with type SQUASH. + // entire stack can't fit in hardware, FIXME // // @layers: a map of index:layer of layers to composite - // @use_squash_fb: reserve a squash framebuffer // @primary_planes: a vector of primary planes available for this frame // @overlay_planes: a vector of overlay planes available for this frame // // Returns: A tuple with the status of the operation (0 for success) and // a vector of the resulting plan (ie: layer->plane mapping). std::tuple> ProvisionPlanes( - std::map &layers, bool use_squash_fb, + std::map &layers, DrmCrtc *crtc, std::vector *primary_planes, std::vector *overlay_planes); @@ -156,18 +127,6 @@ class PlanStageProtected : public Planner::PlanStage { std::vector *planes); }; -// This plan stage provisions the precomp plane with any remaining layers that -// are on top of the current precomp layers. This stage should be included in -// all platforms before loosely allocating layers (i.e. PlanStageGreedy) if -// any previous plan could have modified the precomp plane layers -// (ex. PlanStageProtected). -class PlanStagePrecomp : public Planner::PlanStage { - public: - int ProvisionPlanes(std::vector *composition, - std::map &layers, DrmCrtc *crtc, - std::vector *planes); -}; - // This plan stage places as many layers on dedicated planes as possible (first // come first serve), and then sticks the rest in a precomposition plane (if // needed). diff --git a/platformdrmgeneric.cpp b/platformdrmgeneric.cpp index 82539676b229..5b42c4aed5a4 100644 --- a/platformdrmgeneric.cpp +++ b/platformdrmgeneric.cpp @@ -27,7 +27,6 @@ #include #include #include -#include namespace android { @@ -84,22 +83,6 @@ uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) { } } -EGLImageKHR DrmGenericImporter::ImportImage(EGLDisplay egl_display, buffer_handle_t handle) { - gralloc_handle_t *gr_handle = gralloc_handle(handle); - if (!gr_handle) - return NULL; - EGLint attr[] = { - EGL_WIDTH, (EGLint)gr_handle->width, - EGL_HEIGHT, (EGLint)gr_handle->height, - EGL_LINUX_DRM_FOURCC_EXT, (EGLint)ConvertHalFormatToDrm(gr_handle->format), - EGL_DMA_BUF_PLANE0_FD_EXT, gr_handle->prime_fd, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, - EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)gr_handle->stride, - EGL_NONE, - }; - return eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr); -} - int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { gralloc_handle_t *gr_handle = gralloc_handle(handle); if (!gr_handle) diff --git a/platformdrmgeneric.h b/platformdrmgeneric.h index fbe059b49a92..0339e1e3957e 100644 --- a/platformdrmgeneric.h +++ b/platformdrmgeneric.h @@ -31,7 +31,6 @@ class DrmGenericImporter : public Importer { int Init(); - EGLImageKHR ImportImage(EGLDisplay egl_display, buffer_handle_t handle) override; int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override; int ReleaseBuffer(hwc_drm_bo_t *bo) override; diff --git a/platformhisi.cpp b/platformhisi.cpp index 3f5c31995c57..1ea1d0776648 100644 --- a/platformhisi.cpp +++ b/platformhisi.cpp @@ -69,27 +69,6 @@ int HisiImporter::Init() { return 0; } -EGLImageKHR HisiImporter::ImportImage(EGLDisplay egl_display, buffer_handle_t handle) { - private_handle_t const *hnd = reinterpret_cast < private_handle_t const *>(handle); - if (!hnd) - return NULL; - - EGLint fmt = ConvertHalFormatToDrm(hnd->req_format); - if (fmt < 0) - return NULL; - - EGLint attr[] = { - EGL_WIDTH, hnd->width, - EGL_HEIGHT, hnd->height, - EGL_LINUX_DRM_FOURCC_EXT, fmt, - EGL_DMA_BUF_PLANE0_FD_EXT, hnd->share_fd, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, - EGL_DMA_BUF_PLANE0_PITCH_EXT, hnd->byte_stride, - EGL_NONE, - }; - return eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr); -} - int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { private_handle_t const *hnd = reinterpret_cast < private_handle_t const *>(handle); if (!hnd) @@ -131,5 +110,3 @@ std::unique_ptr Planner::CreateInstance(DrmResources *) { return planner; } } - - diff --git a/platformhisi.h b/platformhisi.h index 46f459513dff..a0986923d4d3 100644 --- a/platformhisi.h +++ b/platformhisi.h @@ -34,7 +34,6 @@ class HisiImporter : public DrmGenericImporter { int Init(); - EGLImageKHR ImportImage(EGLDisplay egl_display, buffer_handle_t handle) override; int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override; private: diff --git a/platformminigbm.cpp b/platformminigbm.cpp index 80e2c0f9f5fd..8e3cc65f0c4c 100644 --- a/platformminigbm.cpp +++ b/platformminigbm.cpp @@ -66,22 +66,6 @@ int DrmMinigbmImporter::Init() { return 0; } -EGLImageKHR DrmMinigbmImporter::ImportImage(EGLDisplay egl_display, buffer_handle_t handle) { - cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle; - if (!gr_handle) - return NULL; - EGLint attr[] = { - EGL_WIDTH, (EGLint)gr_handle->width, - EGL_HEIGHT, (EGLint)gr_handle->height, - EGL_LINUX_DRM_FOURCC_EXT, (EGLint)gr_handle->format, - EGL_DMA_BUF_PLANE0_FD_EXT, gr_handle->fds[0], - EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)gr_handle->strides[0], - EGL_DMA_BUF_PLANE0_OFFSET_EXT, (EGLint)gr_handle->offsets[0], - EGL_NONE, - }; - return eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr); -} - int DrmMinigbmImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle; if (!gr_handle) diff --git a/platformminigbm.h b/platformminigbm.h index ded4c077e178..f25bf7bc2d19 100644 --- a/platformminigbm.h +++ b/platformminigbm.h @@ -32,7 +32,6 @@ class DrmMinigbmImporter : public DrmGenericImporter { int Init(); - EGLImageKHR ImportImage(EGLDisplay egl_display, buffer_handle_t handle) override; int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override; private: diff --git a/virtualcompositorworker.cpp b/virtualcompositorworker.cpp deleted file mode 100644 index b64b4148ee50..000000000000 --- a/virtualcompositorworker.cpp +++ /dev/null @@ -1,168 +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-virtual-compositor-worker" - -#include "virtualcompositorworker.h" -#include "worker.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace android { - -static const int kMaxQueueDepth = 3; -static const int kAcquireWaitTimeoutMs = 3000; - -VirtualCompositorWorker::VirtualCompositorWorker() - : Worker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY), - timeline_fd_(-1), - timeline_(0), - timeline_current_(0) { -} - -VirtualCompositorWorker::~VirtualCompositorWorker() { - if (timeline_fd_ >= 0) { - FinishComposition(timeline_); - close(timeline_fd_); - timeline_fd_ = -1; - } -} - -int VirtualCompositorWorker::Init() { - int ret = sw_sync_timeline_create(); - if (ret < 0) { - ALOGE("Failed to create sw sync timeline %d", ret); - return ret; - } - timeline_fd_ = ret; - return InitWorker(); -} - -void VirtualCompositorWorker::QueueComposite(hwc_display_contents_1_t *dc) { - std::unique_ptr composition(new VirtualComposition); - - composition->outbuf_acquire_fence.Set(dc->outbufAcquireFenceFd); - dc->outbufAcquireFenceFd = -1; - if (dc->retireFenceFd >= 0) - close(dc->retireFenceFd); - dc->retireFenceFd = CreateNextTimelineFence(); - - for (size_t i = 0; i < dc->numHwLayers; ++i) { - hwc_layer_1_t *layer = &dc->hwLayers[i]; - if (layer->flags & HWC_SKIP_LAYER) - continue; - composition->layer_acquire_fences.emplace_back(layer->acquireFenceFd); - layer->acquireFenceFd = -1; - if (layer->releaseFenceFd >= 0) - close(layer->releaseFenceFd); - layer->releaseFenceFd = CreateNextTimelineFence(); - } - - composition->release_timeline = timeline_; - - Lock(); - while (composite_queue_.size() >= kMaxQueueDepth) { - Unlock(); - sched_yield(); - Lock(); - } - - composite_queue_.push(std::move(composition)); - Unlock(); - Signal(); -} - -void VirtualCompositorWorker::Routine() { - int wait_ret = 0; - - Lock(); - if (composite_queue_.empty()) { - wait_ret = WaitForSignalOrExitLocked(); - } - - std::unique_ptr composition; - if (!composite_queue_.empty()) { - composition = std::move(composite_queue_.front()); - composite_queue_.pop(); - } - Unlock(); - - if (wait_ret == -EINTR) { - return; - } else if (wait_ret) { - ALOGE("Failed to wait for signal, %d", wait_ret); - return; - } - - Compose(std::move(composition)); -} - -int VirtualCompositorWorker::CreateNextTimelineFence() { - ++timeline_; - return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_); -} - -int VirtualCompositorWorker::FinishComposition(int point) { - int timeline_increase = point - timeline_current_; - if (timeline_increase <= 0) - return 0; - int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase); - if (ret) - ALOGE("Failed to increment sync timeline %d", ret); - else - timeline_current_ = point; - return ret; -} - -void VirtualCompositorWorker::Compose( - std::unique_ptr composition) { - if (!composition.get()) - return; - - int ret; - int outbuf_acquire_fence = composition->outbuf_acquire_fence.get(); - if (outbuf_acquire_fence >= 0) { - ret = sync_wait(outbuf_acquire_fence, kAcquireWaitTimeoutMs); - if (ret) { - ALOGE("Failed to wait for outbuf acquire %d/%d", outbuf_acquire_fence, - ret); - return; - } - composition->outbuf_acquire_fence.Close(); - } - for (size_t i = 0; i < composition->layer_acquire_fences.size(); ++i) { - int layer_acquire_fence = composition->layer_acquire_fences[i].get(); - if (layer_acquire_fence >= 0) { - ret = sync_wait(layer_acquire_fence, kAcquireWaitTimeoutMs); - if (ret) { - ALOGE("Failed to wait for layer acquire %d/%d", layer_acquire_fence, - ret); - return; - } - composition->layer_acquire_fences[i].Close(); - } - } - FinishComposition(composition->release_timeline); -} -} diff --git a/virtualcompositorworker.h b/virtualcompositorworker.h deleted file mode 100644 index 1fc5e435eaac..000000000000 --- a/virtualcompositorworker.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_VIRTUAL_COMPOSITOR_WORKER_H_ -#define ANDROID_VIRTUAL_COMPOSITOR_WORKER_H_ - -#include "drmhwcomposer.h" -#include "worker.h" - -#include - -namespace android { - -class VirtualCompositorWorker : public Worker { - public: - VirtualCompositorWorker(); - ~VirtualCompositorWorker() override; - - int Init(); - void QueueComposite(hwc_display_contents_1_t *dc); - - protected: - void Routine() override; - - private: - struct VirtualComposition { - UniqueFd outbuf_acquire_fence; - std::vector layer_acquire_fences; - int release_timeline; - }; - - int CreateNextTimelineFence(); - int FinishComposition(int timeline); - void Compose(std::unique_ptr composition); - - std::queue> composite_queue_; - int timeline_fd_; - int timeline_; - int timeline_current_; -}; -} - -#endif