diff options
author | Haixia Shi <hshi@chromium.org> | 2015-10-22 18:12:49 -0700 |
---|---|---|
committer | Haixia Shi <hshi@chromium.org> | 2015-10-27 14:01:11 -0700 |
commit | dda2fabb6a8010768e199210b934a6326c891c2d (patch) | |
tree | 07ee0f9d1246b80636fcada7c8fdfc4a15220fdf /drmdisplaycompositor.cpp | |
parent | 36d7c6e7ddb2e941f8611502ca938189290ff4b2 (diff) |
drm_hwcomposer: move atomic modeset calls into a separate worker
We are currently using synchronous (blocking) atomic modeset calls
which unnecessarily delays GL.
BUG=25126188
TEST=check timestamp of SignalPreCompDone relative to hwc_set
Change-Id: Iba70c1c9591e467c1627516af123a43206da99fd
Diffstat (limited to 'drmdisplaycompositor.cpp')
-rw-r--r-- | drmdisplaycompositor.cpp | 183 |
1 files changed, 138 insertions, 45 deletions
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp index c3042f5..3f41fca 100644 --- a/drmdisplaycompositor.cpp +++ b/drmdisplaycompositor.cpp @@ -35,7 +35,7 @@ #include <sync/sync.h> #include <utils/Trace.h> -#define DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH 3 +#define DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH 2 namespace android { @@ -174,10 +174,68 @@ static bool UsesSquash(const std::vector<DrmCompositionPlane> &comp_planes) { }); } +DrmDisplayCompositor::FrameWorker::FrameWorker(DrmDisplayCompositor *compositor) + : Worker("frame-worker", HAL_PRIORITY_URGENT_DISPLAY), + compositor_(compositor) { +} + +DrmDisplayCompositor::FrameWorker::~FrameWorker() { +} + +int DrmDisplayCompositor::FrameWorker::Init() { + return InitWorker(); +} + +void DrmDisplayCompositor::FrameWorker::QueueFrame( + std::unique_ptr<DrmDisplayComposition> composition, int status) { + Lock(); + FrameState frame; + frame.composition = std::move(composition); + frame.status = status; + frame_queue_.push(std::move(frame)); + SignalLocked(); + Unlock(); +} + +void DrmDisplayCompositor::FrameWorker::Routine() { + int ret = Lock(); + if (ret) { + ALOGE("Failed to lock worker, %d", ret); + return; + } + + int wait_ret = 0; + if (frame_queue_.empty()) { + wait_ret = WaitForSignalOrExitLocked(); + } + + FrameState frame; + if (!frame_queue_.empty()) { + frame = std::move(frame_queue_.front()); + frame_queue_.pop(); + } + + ret = Unlock(); + if (ret) { + ALOGE("Failed to unlock worker, %d", ret); + return; + } + + if (wait_ret == -EINTR) { + return; + } else if (wait_ret) { + ALOGE("Failed to wait for signal, %d", wait_ret); + return; + } + + compositor_->ApplyFrame(std::move(frame.composition), frame.status); +} + DrmDisplayCompositor::DrmDisplayCompositor() : drm_(NULL), display_(-1), worker_(this), + frame_worker_(this), initialized_(false), active_(false), needs_modeset_(false), @@ -196,6 +254,7 @@ DrmDisplayCompositor::~DrmDisplayCompositor() { return; worker_.Exit(); + frame_worker_.Exit(); int ret = pthread_mutex_lock(&lock_); if (ret) @@ -229,6 +288,12 @@ int DrmDisplayCompositor::Init(DrmResources *drm, int display) { ALOGE("Failed to initialize compositor worker %d\n", ret); return ret; } + ret = frame_worker_.Init(); + if (ret) { + pthread_mutex_destroy(&lock_); + ALOGE("Failed to initialize frame worker %d\n", ret); + return ret; + } initialized_ = true; return 0; @@ -438,7 +503,7 @@ int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { return 0; } -int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) { +int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) { int ret = 0; std::vector<DrmHwcLayer> &layers = display_comp->layers(); @@ -497,6 +562,39 @@ int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) { framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; } + for (DrmCompositionPlane &comp_plane : comp_planes) { + switch (comp_plane.source_layer) { + case DrmCompositionPlane::kSourceSquash: + comp_plane.source_layer = squash_layer_index; + break; + case DrmCompositionPlane::kSourcePreComp: + if (!do_pre_comp) { + ALOGE( + "Can not use pre composite framebuffer with no pre composite " + "regions"); + return -EINVAL; + } + comp_plane.source_layer = pre_comp_layer_index; + break; + default: + break; + } + } + + return ret; +} + +int DrmDisplayCompositor::CommitFrame(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> &pre_comp_regions = + display_comp->pre_comp_regions(); + + DrmFramebuffer *pre_comp_fb; + DrmConnector *connector = drm_->GetConnectorForDisplay(display_); if (!connector) { ALOGE("Could not locate connector for display %d", display_); @@ -568,27 +666,12 @@ int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) { switch (comp_plane.source_layer) { case DrmCompositionPlane::kSourceNone: break; - case DrmCompositionPlane::kSourceSquash: { - DrmHwcLayer &layer = layers[squash_layer_index]; - fb_id = layer.buffer->fb_id; - display_frame = layer.display_frame; - source_crop = layer.source_crop; + case DrmCompositionPlane::kSourceSquash: + ALOGE("Actual source layer index expected for squash layer"); break; - } - case DrmCompositionPlane::kSourcePreComp: { - if (!do_pre_comp) { - ALOGE( - "Can not use pre composite framebuffer with no pre composite " - "regions"); - ret = -EINVAL; - goto out; - } - DrmHwcLayer &layer = layers[pre_comp_layer_index]; - fb_id = layer.buffer->fb_id; - display_frame = layer.display_frame; - source_crop = layer.source_crop; + case DrmCompositionPlane::kSourcePreComp: + ALOGE("Actual source layer index expected for pre-comp layer"); break; - } default: { if (comp_plane.source_layer >= layers.size()) { ALOGE("Source layer index %zu out of bounds %zu", @@ -776,6 +859,38 @@ int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) { return 0; } +void DrmDisplayCompositor::ApplyFrame( + std::unique_ptr<DrmDisplayComposition> composition, int status) { + int ret = status; + + if (!ret) + ret = CommitFrame(composition.get()); + + if (ret) { + ALOGE("Composite failed 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. + if (DisablePlanes(active_composition_.get())) + return; + } + ++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"); + + active_composition_.swap(composition); + + if (!ret) + ret = pthread_mutex_unlock(&lock_); + if (ret) + ALOGE("Failed to release lock for active_composition swap"); +} + int DrmDisplayCompositor::Composite() { ATRACE_CALL(); @@ -813,16 +928,8 @@ int DrmDisplayCompositor::Composite() { switch (composition->type()) { case DRM_COMPOSITION_TYPE_FRAME: - ret = ApplyFrame(composition.get()); - if (ret) { - ALOGE("Composite failed 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. - if (DisablePlanes(active_composition_.get())) - return ret; - } - ++dump_frames_composited_; + ret = PrepareFrame(composition.get()); + frame_worker_.QueueFrame(std::move(composition), ret); break; case DRM_COMPOSITION_TYPE_DPMS: ret = ApplyDpms(composition.get()); @@ -838,20 +945,6 @@ int DrmDisplayCompositor::Composite() { return -EINVAL; } - if (active_composition_) - active_composition_->SignalCompositionDone(); - - ret = pthread_mutex_lock(&lock_); - if (ret) - ALOGE("Failed to acquire lock for active_composition swap"); - - active_composition_.swap(composition); - - if (!ret) - ret = pthread_mutex_unlock(&lock_); - if (ret) - ALOGE("Failed to release lock for active_composition swap"); - return ret; } |