Message ID | 20180504191833.6967-1-robh@kernel.org |
---|---|
State | New |
Headers | show |
Series | [hwc] drm_hwcomposer: Remove GL compositing support | expand |
On Fri, May 04, 2018 at 02:18:33PM -0500, Rob Herring wrote: > 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. Hey Rob, Thanks for posting this so quickly, I think it's definitely a step in the right direction. I've posted this as a merge request on gitlab [1] with the reverts squashed into the change. I don't think this will conflict too badly with Alex's work, but I want him to take a look at it first before merging. Sean [1]- https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer/merge_requests/6 > > Signed-off-by: Rob Herring <robh@kernel.org> > --- > 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 <memory> > -#define EGL_EGLEXT_PROTOTYPES > -#define GL_GLEXT_PROTOTYPES > - > -#include <EGL/egl.h> > -#include <EGL/eglext.h> > -#include <GLES2/gl2.h> > -#include <GLES2/gl2ext.h> > - > -// 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<type, name##Deleter> 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 <stdlib.h> > - > -#include <log/log.h> > -#include <hardware/hardware.h> > - > -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 <unordered_set> > > #include <log/log.h> > -#include <sw_sync.h> > #include <sync/sync.h> > #include <xf86drmMode.h> > > 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<size_t> SetBitsToVector( > - uint64_t in, const std::vector<size_t> &index_map) { > - std::vector<size_t> 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<int> *exclude_rects, > - size_t num_exclude_rects) { > - DrmCompositionPlane *comp = NULL; > +void DrmDisplayComposition::SeparateLayers(DrmHwcRect<int> *, > + size_t ) { > std::vector<size_t> 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<size_t> &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<DrmHwcRect<int>> 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_rects::RectSet<uint64_t, int>> 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<uint64_t, int> ®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<DrmHwcLayer *> squash_layers; > - std::unordered_set<DrmHwcLayer *> pre_comp_layers; > - std::unordered_set<DrmHwcLayer *> 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<DrmPlane *> *primary_planes, > +int DrmDisplayComposition::Plan(std::vector<DrmPlane *> *primary_planes, > std::vector<DrmPlane *> *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<size_t, DrmHwcLayer *> to_composite; > > - bool use_squash_framebuffer = false; > - // Used to determine which layers were entirely squashed > - std::vector<int> layer_squash_area(layers_.size(), 0); > - // Used to avoid rerendering regions that were squashed > - std::vector<DrmHwcRect<int>> exclude_rects; > - if (squash != NULL) { > - if (geometry_changed_) { > - squash->Init(layers_.data(), layers_.size()); > - } else { > - std::vector<bool> changed_regions; > - squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions); > - > - std::vector<bool> 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<DrmCompositionPlane> 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<int> *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<size_t> &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 << "<invalid>"; > 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 <sstream> > #include <vector> > @@ -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<DrmPlane *> *primary_planes, > + int Plan(std::vector<DrmPlane *> *primary_planes, > std::vector<DrmPlane *> *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<DrmHwcLayer> &layers() { > return layers_; > } > > - std::vector<DrmCompositionRegion> &squash_regions() { > - return squash_regions_; > - } > - > - std::vector<DrmCompositionRegion> &pre_comp_regions() { > - return pre_comp_regions_; > - } > - > std::vector<DrmCompositionPlane> &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<int> *exclude_rects, > size_t num_exclude_rects); > void SeparateLayers(DrmHwcRect<int> *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<DrmHwcLayer> layers_; > - std::vector<DrmCompositionRegion> squash_regions_; > - std::vector<DrmCompositionRegion> pre_comp_regions_; > std::vector<DrmCompositionPlane> 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<DrmHwcRect<int>> 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<separate_rects::RectSet<uint64_t, int>> out_regions; > - separate_rects::separate_rects_64(in_rects, &out_regions); > - > - for (const separate_rects::RectSet<uint64_t, int> &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<bool> &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<kMaxLayers> 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<bool> &changed_regions, > - std::vector<bool> &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<bool> &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<bool> &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<kMaxLayers>((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<DrmCompositionPlane> &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<float>(0, 0, width, height); > - pre_comp_layer.display_frame = DrmHwcRect<int>(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<DrmCompositionRegion> ®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<DrmCompositionRegion> ®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<DrmHwcLayer> &layers = display_comp->layers(); > - std::vector<DrmCompositionPlane> &comp_planes = > - display_comp->composition_planes(); > - std::vector<DrmCompositionRegion> &squash_regions = > - display_comp->squash_regions(); > - std::vector<DrmCompositionRegion> &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<float>( > - 0, 0, squash_layer.buffer->width, squash_layer.buffer->height); > - squash_layer.display_frame = DrmHwcRect<int>( > - 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<size_t> &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<DrmDisplayComposition> 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<DrmDisplayComposition> 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<DrmCompositionPlane> &src_planes = src->composition_planes(); > - std::vector<DrmHwcLayer> &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<DrmHwcLayer> 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<int> rect; > - std::bitset<kMaxLayers> layer_refs; > - std::bitset<kHistoryLength> 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<Region> ®ions() const { > - return regions_; > - } > - > - void Init(DrmHwcLayer *layers, size_t num_layers); > - void GenerateHistory(DrmHwcLayer *layers, size_t num_layers, > - std::vector<bool> &changed_regions) const; > - void StableRegionsWithMarginalHistory( > - const std::vector<bool> &changed_regions, > - std::vector<bool> &stable_regions) const; > - void RecordHistory(DrmHwcLayer *layers, size_t num_layers, > - const std::vector<bool> &changed_regions); > - bool RecordAndCompareSquashed(const std::vector<bool> &squashed_regions); > - > - void Dump(std::ostringstream *out) const; > - > - private: > - size_t generation_number_ = 0; > - unsigned valid_history_ = 0; > - std::vector<buffer_handle_t> last_handles_; > - > - std::vector<Region> regions_; > -}; > - > class DrmDisplayCompositor { > public: > DrmDisplayCompositor(); > @@ -89,15 +46,10 @@ class DrmDisplayCompositor { > std::unique_ptr<DrmDisplayComposition> CreateComposition() const; > int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition); > int Composite(); > - int SquashAll(); > void Dump(std::ostringstream *out) const; > > std::tuple<uint32_t, uint32_t, int> 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<GLWorkerCompositor> 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<DrmPlane *> primary_planes(primary_planes_); > std::vector<DrmPlane *> 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 <algorithm> > -#include <string> > -#include <sstream> > -#include <unordered_set> > - > -#include <sys/resource.h> > - > -#include <cutils/properties.h> > - > -#include <hardware/hardware.h> > -#include <hardware/hwcomposer.h> > - > -#include <ui/GraphicBuffer.h> > -#include <ui/PixelFormat.h> > - > -#include <utils/Trace.h> > - > -#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<float> 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<float> 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<GraphicBuffer> &framebuffer, > - Importer *importer) { > - ATRACE_CALL(); > - int ret = 0; > - std::vector<AutoEGLImageAndGLTexture> layer_textures; > - std::vector<RenderingCommand> 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<size_t> 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<GraphicBuffer> &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<GraphicBuffer> &framebuffer) { > - for (auto &fb : cached_framebuffers_) > - if (fb.weak_framebuffer == framebuffer) > - return &fb; > - return NULL; > -} > - > -GLWorkerCompositor::CachedFramebuffer * > -GLWorkerCompositor::PrepareAndCacheFramebuffer( > - const sp<GraphicBuffer> &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 <vector> > - > -#define EGL_EGLEXT_PROTOTYPES > -#define GL_GLEXT_PROTOTYPES > - > -#include <EGL/egl.h> > -#include <EGL/eglext.h> > -#include <GLES2/gl2.h> > -#include <GLES2/gl2ext.h> > - > -#include <ui/GraphicBuffer.h> > - > -#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<GraphicBuffer> &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<GraphicBuffer> strong_framebuffer; > - wp<GraphicBuffer> weak_framebuffer; > - AutoEGLDisplayImage egl_fb_image; > - AutoGLTexture gl_fb_tex; > - AutoGLFramebuffer gl_fb; > - > - CachedFramebuffer(const sp<GraphicBuffer> &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<GraphicBuffer> &framebuffer); > - CachedFramebuffer *PrepareAndCacheFramebuffer( > - const sp<GraphicBuffer> &framebuffer); > - > - GLint PrepareAndCacheProgram(unsigned texture_count); > - > - EGLDisplay egl_display_; > - EGLContext egl_ctx_; > - > - std::vector<AutoGLProgram> blend_programs_; > - AutoGLBuffer vertex_buffer_; > - > - std::vector<CachedFramebuffer> 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 <stdlib.h> > - > -#include <cinttypes> > -#include <map> > -#include <vector> > -#include <sstream> > - > -#include <errno.h> > -#include <fcntl.h> > -#include <pthread.h> > -#include <sys/param.h> > -#include <sys/resource.h> > -#include <xf86drm.h> > -#include <xf86drmMode.h> > - > -#include <log/log.h> > -#include <cutils/properties.h> > -#include <hardware/hardware.h> > -#include <hardware/hwcomposer.h> > -#include <sw_sync.h> > -#include <sync/sync.h> > -#include <utils/Trace.h> > - > -#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<uint32_t> 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<int, hwc_drm_display_t> 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> 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<int, int> &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<int, int> 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<CheckedOutputFd> checked_output_fences; > - std::vector<DrmHwcDisplayContents> displays_contents; > - std::vector<DrmCompositionDisplayLayersMap> layers_map; > - std::vector<std::vector<size_t>> 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<size_t> &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<size_t> &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<DrmComposition> 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<const int, hwc_drm_display> &display_entry : ctx->displays) { > - auto callback = std::make_shared<DrmVsyncCallback>(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<hwc_context_t> 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<hw_module_t *>(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<DrmPlane *> Planner::GetUsablePlanes( > } > > std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes( > - std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, DrmCrtc *crtc, > + std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, > std::vector<DrmPlane *> *primary_planes, > std::vector<DrmPlane *> *overlay_planes) { > std::vector<DrmCompositionPlane> composition; > @@ -48,30 +48,6 @@ std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes( > return std::make_tuple(-ENODEV, std::vector<DrmCompositionPlane>()); > } > > - // 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<int, std::vector<DrmCompositionPlane>> 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<size_t>(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<DrmCompositionPlane> *composition, > - std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc * /*crtc*/, > - std::vector<DrmPlane *> * /*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<DrmCompositionPlane> *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<DrmCompositionPlane> *composition, > std::vector<DrmPlane *> *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<DrmCompositionPlane>::iterator GetPrecompIter( > - std::vector<DrmCompositionPlane> *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<Planner> 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<int, std::vector<DrmCompositionPlane>> ProvisionPlanes( > - std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, > + std::map<size_t, DrmHwcLayer *> &layers, > DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, > std::vector<DrmPlane *> *overlay_planes); > > @@ -156,18 +127,6 @@ class PlanStageProtected : public Planner::PlanStage { > std::vector<DrmPlane *> *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<DrmCompositionPlane> *composition, > - std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, > - std::vector<DrmPlane *> *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 <log/log.h> > #include <gralloc_handle.h> > #include <hardware/gralloc.h> > -#include <EGL/eglext.h> > > 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> 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 <errno.h> > -#include <stdlib.h> > - > -#include <log/log.h> > -#include <hardware/hardware.h> > -#include <hardware/hwcomposer.h> > -#include <sched.h> > -#include <sw_sync.h> > -#include <sync/sync.h> > - > -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<VirtualComposition> 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<VirtualComposition> 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<VirtualComposition> 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 <queue> > - > -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<UniqueFd> layer_acquire_fences; > - int release_timeline; > - }; > - > - int CreateNextTimelineFence(); > - int FinishComposition(int timeline); > - void Compose(std::unique_ptr<VirtualComposition> composition); > - > - std::queue<std::unique_ptr<VirtualComposition>> composite_queue_; > - int timeline_fd_; > - int timeline_; > - int timeline_current_; > -}; > -} > - > -#endif > -- > 2.17.0 >
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 <memory> -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -// 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<type, name##Deleter> 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 <stdlib.h> - -#include <log/log.h> -#include <hardware/hardware.h> - -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 <unordered_set> #include <log/log.h> -#include <sw_sync.h> #include <sync/sync.h> #include <xf86drmMode.h> 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<size_t> SetBitsToVector( - uint64_t in, const std::vector<size_t> &index_map) { - std::vector<size_t> 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<int> *exclude_rects, - size_t num_exclude_rects) { - DrmCompositionPlane *comp = NULL; +void DrmDisplayComposition::SeparateLayers(DrmHwcRect<int> *, + size_t ) { std::vector<size_t> 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<size_t> &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<DrmHwcRect<int>> 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_rects::RectSet<uint64_t, int>> 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<uint64_t, int> ®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<DrmHwcLayer *> squash_layers; - std::unordered_set<DrmHwcLayer *> pre_comp_layers; - std::unordered_set<DrmHwcLayer *> 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<DrmPlane *> *primary_planes, +int DrmDisplayComposition::Plan(std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *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<size_t, DrmHwcLayer *> to_composite; - bool use_squash_framebuffer = false; - // Used to determine which layers were entirely squashed - std::vector<int> layer_squash_area(layers_.size(), 0); - // Used to avoid rerendering regions that were squashed - std::vector<DrmHwcRect<int>> exclude_rects; - if (squash != NULL) { - if (geometry_changed_) { - squash->Init(layers_.data(), layers_.size()); - } else { - std::vector<bool> changed_regions; - squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions); - - std::vector<bool> 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<DrmCompositionPlane> 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<int> *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<size_t> &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 << "<invalid>"; 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 <sstream> #include <vector> @@ -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<DrmPlane *> *primary_planes, + int Plan(std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *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<DrmHwcLayer> &layers() { return layers_; } - std::vector<DrmCompositionRegion> &squash_regions() { - return squash_regions_; - } - - std::vector<DrmCompositionRegion> &pre_comp_regions() { - return pre_comp_regions_; - } - std::vector<DrmCompositionPlane> &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<int> *exclude_rects, size_t num_exclude_rects); void SeparateLayers(DrmHwcRect<int> *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<DrmHwcLayer> layers_; - std::vector<DrmCompositionRegion> squash_regions_; - std::vector<DrmCompositionRegion> pre_comp_regions_; std::vector<DrmCompositionPlane> 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<DrmHwcRect<int>> 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<separate_rects::RectSet<uint64_t, int>> out_regions; - separate_rects::separate_rects_64(in_rects, &out_regions); - - for (const separate_rects::RectSet<uint64_t, int> &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<bool> &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<kMaxLayers> 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<bool> &changed_regions, - std::vector<bool> &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<bool> &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<bool> &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<kMaxLayers>((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<DrmCompositionPlane> &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<float>(0, 0, width, height); - pre_comp_layer.display_frame = DrmHwcRect<int>(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<DrmCompositionRegion> ®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<DrmCompositionRegion> ®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<DrmHwcLayer> &layers = display_comp->layers(); - std::vector<DrmCompositionPlane> &comp_planes = - display_comp->composition_planes(); - std::vector<DrmCompositionRegion> &squash_regions = - display_comp->squash_regions(); - std::vector<DrmCompositionRegion> &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<float>( - 0, 0, squash_layer.buffer->width, squash_layer.buffer->height); - squash_layer.display_frame = DrmHwcRect<int>( - 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<size_t> &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<DrmDisplayComposition> 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<DrmDisplayComposition> 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<DrmCompositionPlane> &src_planes = src->composition_planes(); - std::vector<DrmHwcLayer> &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<DrmHwcLayer> 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<int> rect; - std::bitset<kMaxLayers> layer_refs; - std::bitset<kHistoryLength> 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<Region> ®ions() const { - return regions_; - } - - void Init(DrmHwcLayer *layers, size_t num_layers); - void GenerateHistory(DrmHwcLayer *layers, size_t num_layers, - std::vector<bool> &changed_regions) const; - void StableRegionsWithMarginalHistory( - const std::vector<bool> &changed_regions, - std::vector<bool> &stable_regions) const; - void RecordHistory(DrmHwcLayer *layers, size_t num_layers, - const std::vector<bool> &changed_regions); - bool RecordAndCompareSquashed(const std::vector<bool> &squashed_regions); - - void Dump(std::ostringstream *out) const; - - private: - size_t generation_number_ = 0; - unsigned valid_history_ = 0; - std::vector<buffer_handle_t> last_handles_; - - std::vector<Region> regions_; -}; - class DrmDisplayCompositor { public: DrmDisplayCompositor(); @@ -89,15 +46,10 @@ class DrmDisplayCompositor { std::unique_ptr<DrmDisplayComposition> CreateComposition() const; int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition); int Composite(); - int SquashAll(); void Dump(std::ostringstream *out) const; std::tuple<uint32_t, uint32_t, int> 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<GLWorkerCompositor> 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<DrmPlane *> primary_planes(primary_planes_); std::vector<DrmPlane *> 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 <algorithm> -#include <string> -#include <sstream> -#include <unordered_set> - -#include <sys/resource.h> - -#include <cutils/properties.h> - -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> - -#include <ui/GraphicBuffer.h> -#include <ui/PixelFormat.h> - -#include <utils/Trace.h> - -#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<float> 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<float> 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<GraphicBuffer> &framebuffer, - Importer *importer) { - ATRACE_CALL(); - int ret = 0; - std::vector<AutoEGLImageAndGLTexture> layer_textures; - std::vector<RenderingCommand> 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<size_t> 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<GraphicBuffer> &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<GraphicBuffer> &framebuffer) { - for (auto &fb : cached_framebuffers_) - if (fb.weak_framebuffer == framebuffer) - return &fb; - return NULL; -} - -GLWorkerCompositor::CachedFramebuffer * -GLWorkerCompositor::PrepareAndCacheFramebuffer( - const sp<GraphicBuffer> &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 <vector> - -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#include <ui/GraphicBuffer.h> - -#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<GraphicBuffer> &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<GraphicBuffer> strong_framebuffer; - wp<GraphicBuffer> weak_framebuffer; - AutoEGLDisplayImage egl_fb_image; - AutoGLTexture gl_fb_tex; - AutoGLFramebuffer gl_fb; - - CachedFramebuffer(const sp<GraphicBuffer> &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<GraphicBuffer> &framebuffer); - CachedFramebuffer *PrepareAndCacheFramebuffer( - const sp<GraphicBuffer> &framebuffer); - - GLint PrepareAndCacheProgram(unsigned texture_count); - - EGLDisplay egl_display_; - EGLContext egl_ctx_; - - std::vector<AutoGLProgram> blend_programs_; - AutoGLBuffer vertex_buffer_; - - std::vector<CachedFramebuffer> 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 <stdlib.h> - -#include <cinttypes> -#include <map> -#include <vector> -#include <sstream> - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <sys/param.h> -#include <sys/resource.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include <log/log.h> -#include <cutils/properties.h> -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> -#include <sw_sync.h> -#include <sync/sync.h> -#include <utils/Trace.h> - -#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<uint32_t> 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<int, hwc_drm_display_t> 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> 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<int, int> &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<int, int> 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<CheckedOutputFd> checked_output_fences; - std::vector<DrmHwcDisplayContents> displays_contents; - std::vector<DrmCompositionDisplayLayersMap> layers_map; - std::vector<std::vector<size_t>> 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<size_t> &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<size_t> &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<DrmComposition> 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<const int, hwc_drm_display> &display_entry : ctx->displays) { - auto callback = std::make_shared<DrmVsyncCallback>(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<hwc_context_t> 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<hw_module_t *>(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<DrmPlane *> Planner::GetUsablePlanes( } std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes( - std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, DrmCrtc *crtc, + std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *overlay_planes) { std::vector<DrmCompositionPlane> composition; @@ -48,30 +48,6 @@ std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes( return std::make_tuple(-ENODEV, std::vector<DrmCompositionPlane>()); } - // 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<int, std::vector<DrmCompositionPlane>> 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<size_t>(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<DrmCompositionPlane> *composition, - std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc * /*crtc*/, - std::vector<DrmPlane *> * /*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<DrmCompositionPlane> *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<DrmCompositionPlane> *composition, std::vector<DrmPlane *> *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<DrmCompositionPlane>::iterator GetPrecompIter( - std::vector<DrmCompositionPlane> *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<Planner> 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<int, std::vector<DrmCompositionPlane>> ProvisionPlanes( - std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, + std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *overlay_planes); @@ -156,18 +127,6 @@ class PlanStageProtected : public Planner::PlanStage { std::vector<DrmPlane *> *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<DrmCompositionPlane> *composition, - std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, - std::vector<DrmPlane *> *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 <log/log.h> #include <gralloc_handle.h> #include <hardware/gralloc.h> -#include <EGL/eglext.h> 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> 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 <errno.h> -#include <stdlib.h> - -#include <log/log.h> -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> -#include <sched.h> -#include <sw_sync.h> -#include <sync/sync.h> - -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<VirtualComposition> 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<VirtualComposition> 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<VirtualComposition> 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 <queue> - -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<UniqueFd> layer_acquire_fences; - int release_timeline; - }; - - int CreateNextTimelineFence(); - int FinishComposition(int timeline); - void Compose(std::unique_ptr<VirtualComposition> composition); - - std::queue<std::unique_ptr<VirtualComposition>> composite_queue_; - int timeline_fd_; - int timeline_; - int timeline_current_; -}; -} - -#endif
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 <robh@kernel.org> --- 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