summaryrefslogtreecommitdiffstats
path: root/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
blob: b2045080b701bde566eaf14c88d47662bf44afe4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"

#include "base/bind.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h"

namespace ui {

HardwareDisplayPlaneManagerLegacy::HardwareDisplayPlaneManagerLegacy() {
}

HardwareDisplayPlaneManagerLegacy::~HardwareDisplayPlaneManagerLegacy() {
}

bool HardwareDisplayPlaneManagerLegacy::Commit(
    HardwareDisplayPlaneList* plane_list,
    bool is_sync) {
  if (plane_list->plane_list.empty())  // No assigned planes, nothing to do.
    return true;
  bool ret = true;
  // The order of operations here (set new planes, pageflip, clear old planes)
  // is designed to minimze the chance of a significant artifact occurring.
  // The planes must be updated first because the main plane no longer contains
  // their content. The old planes are removed last because the previous primary
  // plane used them as overlays and thus didn't contain their content, so we
  // must first flip to the new primary plane, which does. The error here will
  // be the delta of (new contents, old contents), but it should be barely
  // noticeable.
  for (const auto& flip : plane_list->legacy_page_flips) {
    // Permission Denied is a legitimate error
    for (const auto& plane : flip.planes) {
      if (!drm_->PageFlipOverlay(flip.crtc_id, plane.framebuffer, plane.bounds,
                                 plane.src_rect, plane.plane)) {
        PLOG(ERROR) << "Cannot display plane on overlay: crtc=" << flip.crtc
                    << " plane=" << plane.plane;
        ret = false;
        flip.crtc->PageFlipFailed();
        break;
      }
    }
    if (!drm_->PageFlip(flip.crtc_id, flip.framebuffer, is_sync,
                        base::Bind(&CrtcController::OnPageFlipEvent,
                                   flip.crtc->AsWeakPtr()))) {
      if (errno != EACCES) {
        PLOG(ERROR) << "Cannot page flip: crtc=" << flip.crtc_id
                    << " framebuffer=" << flip.framebuffer
                    << " is_sync=" << is_sync;
        ret = false;
      }
      flip.crtc->PageFlipFailed();
    }
  }
  // For each element in |old_plane_list|, if it hasn't been reclaimed (by
  // this or any other HDPL), clear the overlay contents.
  for (HardwareDisplayPlane* plane : plane_list->old_plane_list) {
    if (!plane->in_use() && !plane->is_dummy()) {
      // This plane is being released, so we need to zero it.
      if (!drm_->PageFlipOverlay(plane->owning_crtc(), 0, gfx::Rect(),
                                 gfx::Rect(), plane->plane_id())) {
        PLOG(ERROR) << "Cannot free overlay: crtc=" << plane->owning_crtc()
                    << " plane=" << plane->plane_id();
        ret = false;
        break;
      }
    }
  }
  plane_list->plane_list.swap(plane_list->old_plane_list);
  plane_list->plane_list.clear();
  plane_list->legacy_page_flips.clear();
  plane_list->committed = true;
  return ret;
}

bool HardwareDisplayPlaneManagerLegacy::SetPlaneData(
    HardwareDisplayPlaneList* plane_list,
    HardwareDisplayPlane* hw_plane,
    const OverlayPlane& overlay,
    uint32_t crtc_id,
    const gfx::Rect& src_rect,
    CrtcController* crtc) {
  if (hw_plane->is_dummy() || plane_list->legacy_page_flips.empty() ||
      plane_list->legacy_page_flips.back().crtc_id != crtc_id) {
    plane_list->legacy_page_flips.push_back(
        HardwareDisplayPlaneList::PageFlipInfo(
            crtc_id, overlay.buffer->GetFramebufferId(), crtc));
  } else {
    plane_list->legacy_page_flips.back().planes.push_back(
        HardwareDisplayPlaneList::PageFlipInfo::Plane(
            hw_plane->plane_id(), overlay.buffer->GetFramebufferId(),
            overlay.display_bounds, src_rect));
  }
  return true;
}

}  // namespace ui