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/...
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> *,
std::vector<size_t> dedicated_layers;size_t ) {
- // 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_,
if (ret) { ALOGE("Planner failed provisioning planes ret=%d", ret);planner_->ProvisionPlanes(to_composite, crtc_, primary_planes, overlay_planes);
@@ -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),
struct timespec ts;squash_framebuffer_index_(0), dump_frames_composited_(0), dump_last_timestamp_ns_(0) {
@@ -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; } }
case DRM_COMPOSITION_TYPE_DPMS:ApplyFrame(std::move(composition), ret); break;
@@ -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());
} } return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;break;
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