Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / hardware_display_controller.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/ozone/platform/dri/hardware_display_controller.h"
6
7 #include <drm.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <xf86drm.h>
11
12 #include "base/basictypes.h"
13 #include "base/debug/trace_event.h"
14 #include "base/logging.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "ui/gfx/geometry/point.h"
17 #include "ui/gfx/geometry/size.h"
18 #include "ui/ozone/platform/dri/crtc_controller.h"
19 #include "ui/ozone/platform/dri/dri_buffer.h"
20 #include "ui/ozone/platform/dri/dri_wrapper.h"
21 #include "ui/ozone/public/native_pixmap.h"
22
23 namespace ui {
24
25 namespace {
26
27 // DRM callback on page flip events. This callback is triggered after the
28 // page flip has happened and the backbuffer is now the new frontbuffer
29 // The old frontbuffer is no longer used by the hardware and can be used for
30 // future draw operations.
31 //
32 // |device| will contain a reference to the |ScanoutSurface| object which
33 // the event belongs to.
34 //
35 // TODO(dnicoara) When we have a FD handler for the DRM calls in the message
36 // loop, we can move this function in the handler.
37 void HandlePageFlipEvent(int fd,
38                          unsigned int frame,
39                          unsigned int seconds,
40                          unsigned int useconds,
41                          void* controller) {
42   static_cast<CrtcController*>(controller)
43       ->OnPageFlipEvent(frame, seconds, useconds);
44 }
45
46 }  // namespace
47
48 HardwareDisplayController::HardwareDisplayController(
49     scoped_ptr<CrtcController> controller)
50     : is_disabled_(true) {
51   crtc_controllers_.push_back(controller.release());
52 }
53
54 HardwareDisplayController::~HardwareDisplayController() {
55   // Reset the cursor.
56   UnsetCursor();
57 }
58
59 bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
60                                         drmModeModeInfo mode) {
61   TRACE_EVENT0("dri", "HDC::Modeset");
62   DCHECK(primary.buffer.get());
63   bool status = true;
64   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
65     status &= crtc_controllers_[i]->Modeset(primary, mode);
66
67   current_planes_ = std::vector<OverlayPlane>(1, primary);
68   pending_planes_.clear();
69   is_disabled_ = false;
70   mode_ = mode;
71   return status;
72 }
73
74 bool HardwareDisplayController::Enable() {
75   TRACE_EVENT0("dri", "HDC::Enable");
76   DCHECK(!current_planes_.empty());
77   OverlayPlane primary = OverlayPlane::GetPrimaryPlane(current_planes_);
78   DCHECK(primary.buffer.get());
79   bool status = true;
80   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
81     status &= crtc_controllers_[i]->Modeset(primary, mode_);
82
83   return status;
84 }
85
86 void HardwareDisplayController::Disable() {
87   TRACE_EVENT0("dri", "HDC::Disable");
88   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
89     crtc_controllers_[i]->Disable();
90
91   is_disabled_ = true;
92 }
93
94 void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) {
95   pending_planes_.push_back(plane);
96 }
97
98 bool HardwareDisplayController::SchedulePageFlip() {
99   DCHECK(!pending_planes_.empty());
100
101   if (is_disabled_)
102     return true;
103
104   bool status = true;
105   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
106     status &= crtc_controllers_[i]->SchedulePageFlip(pending_planes_);
107
108   return status;
109 }
110
111 void HardwareDisplayController::WaitForPageFlipEvent() {
112   TRACE_EVENT0("dri", "HDC::WaitForPageFlipEvent");
113
114   drmEventContext drm_event;
115   drm_event.version = DRM_EVENT_CONTEXT_VERSION;
116   drm_event.page_flip_handler = HandlePageFlipEvent;
117   drm_event.vblank_handler = NULL;
118
119   bool has_pending_page_flips = false;
120   // Wait for the page-flips to complete.
121   for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
122     // In mirror mode the page flip callbacks can happen in different order than
123     // scheduled, so we need to make sure that the event for the current CRTC is
124     // processed before moving to the next CRTC.
125     while (crtc_controllers_[i]->page_flip_pending()) {
126       has_pending_page_flips = true;
127       crtc_controllers_[i]->drm()->HandleEvent(drm_event);
128     }
129   }
130
131   // In case there are no pending pageflips do not replace the current planes
132   // since they are still being used.
133   if (has_pending_page_flips)
134     current_planes_.swap(pending_planes_);
135
136   pending_planes_.clear();
137 }
138
139 bool HardwareDisplayController::SetCursor(
140     const scoped_refptr<ScanoutBuffer>& buffer) {
141   bool status = true;
142
143   if (is_disabled_)
144     return true;
145
146   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
147     status &= crtc_controllers_[i]->SetCursor(buffer);
148
149   return status;
150 }
151
152 bool HardwareDisplayController::UnsetCursor() {
153   bool status = true;
154   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
155     status &= crtc_controllers_[i]->UnsetCursor();
156
157   return status;
158 }
159
160 bool HardwareDisplayController::MoveCursor(const gfx::Point& location) {
161   if (is_disabled_)
162     return true;
163
164   bool status = true;
165   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
166     status &= crtc_controllers_[i]->MoveCursor(location);
167
168   return status;
169 }
170
171 void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
172   crtc_controllers_.push_back(controller.release());
173 }
174
175 scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
176     uint32_t crtc) {
177   for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin();
178        it != crtc_controllers_.end(); ++it) {
179     if ((*it)->crtc() == crtc) {
180       scoped_ptr<CrtcController> controller(*it);
181       crtc_controllers_.weak_erase(it);
182       return controller.Pass();
183     }
184   }
185
186   return scoped_ptr<CrtcController>();
187 }
188
189 bool HardwareDisplayController::HasCrtc(uint32_t crtc) const {
190   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
191     if (crtc_controllers_[i]->crtc() == crtc)
192       return true;
193
194   return false;
195 }
196
197 bool HardwareDisplayController::IsMirrored() const {
198   return crtc_controllers_.size() > 1;
199 }
200
201 bool HardwareDisplayController::IsDisabled() const {
202   return is_disabled_;
203 }
204
205 gfx::Size HardwareDisplayController::GetModeSize() const {
206   return gfx::Size(mode_.hdisplay, mode_.vdisplay);
207 }
208
209 uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
210   uint64_t time = 0;
211   for (size_t i = 0; i < crtc_controllers_.size(); ++i)
212     if (time < crtc_controllers_[i]->time_of_last_flip())
213       time = crtc_controllers_[i]->time_of_last_flip();
214
215   return time;
216 }
217
218 }  // namespace ui