Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / hardware_display_controller.h
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 #ifndef UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
6 #define UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <xf86drmMode.h>
11 #include <vector>
12
13 #include "base/basictypes.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "ui/ozone/ozone_export.h"
16 #include "ui/ozone/platform/dri/dri_wrapper.h"
17
18 namespace gfx {
19 class Point;
20 }
21
22 namespace ui {
23
24 class DriSurface;
25
26 // The HDCOz will handle modesettings and scannout operations for hardware
27 // devices.
28 //
29 // In the DRM world there are 3 components that need to be paired up to be able
30 // to display an image to the monitor: CRTC (cathode ray tube controller),
31 // encoder and connector. The CRTC determines which framebuffer to read, when
32 // to scanout and where to scanout. Encoders converts the stream from the CRTC
33 // to the appropriate format for the connector. The connector is the physical
34 // connection that monitors connect to.
35 //
36 // There is no 1:1:1 pairing for these components. It is possible for an encoder
37 // to be compatible to multiple CRTCs and each connector can be used with
38 // multiple encoders. In addition, it is possible to use one CRTC with multiple
39 // connectors such that we can display the same image on multiple monitors.
40 //
41 // For example, the following configuration shows 2 different screens being
42 // initialized separately.
43 // -------------      -------------
44 // | Connector |      | Connector |
45 // |   HDMI    |      |    VGA    |
46 // -------------      -------------
47 //       ^                  ^
48 //       |                  |
49 // -------------      -------------
50 // |  Encoder1  |     |  Encoder2 |
51 // -------------      -------------
52 //       ^                  ^
53 //       |                  |
54 // -------------      -------------
55 // |   CRTC1   |      |   CRTC2   |
56 // -------------      -------------
57 //
58 // In the following configuration 2 different screens are associated with the
59 // same CRTC, so on scanout the same framebuffer will be displayed on both
60 // monitors.
61 // -------------      -------------
62 // | Connector |      | Connector |
63 // |   HDMI    |      |    VGA    |
64 // -------------      -------------
65 //       ^                  ^
66 //       |                  |
67 // -------------      -------------
68 // |  Encoder1  |     |  Encoder2 |
69 // -------------      -------------
70 //       ^                  ^
71 //       |                  |
72 //      ----------------------
73 //      |        CRTC1       |
74 //      ----------------------
75 //
76 // Note that it is possible to have more connectors than CRTCs which means that
77 // only a subset of connectors can be active independently, showing different
78 // framebuffers. Though, in this case, it would be possible to have all
79 // connectors active if some use the same CRTC to mirror the display.
80 //
81 // TODO(dnicoara) Need to have a way to detect events (such as monitor
82 // connected or disconnected).
83 class OZONE_EXPORT HardwareDisplayController {
84  public:
85   HardwareDisplayController(DriWrapper* drm,
86                             uint32_t connector_id,
87                             uint32_t crtc_id);
88
89   ~HardwareDisplayController();
90
91   // Associate the HDCO with a surface implementation and initialize it.
92   bool BindSurfaceToController(scoped_ptr<DriSurface> surface,
93                                drmModeModeInfo mode);
94
95   void UnbindSurfaceFromController();
96
97   // Schedules the |surface_|'s framebuffer to be displayed on the next vsync
98   // event. The event will be posted on the graphics card file descriptor |fd_|
99   // and it can be read and processed by |drmHandleEvent|. That function can
100   // define the callback for the page flip event. A generic data argument will
101   // be presented to the callback. We use that argument to pass in the HDCO
102   // object the event belongs to.
103   //
104   // Between this call and the callback, the framebuffer used in this call
105   // should not be modified in any way as it would cause screen tearing if the
106   // hardware performed the flip. Note that the frontbuffer should also not
107   // be modified as it could still be displayed.
108   //
109   // Note that this function does not block. Also, this function should not be
110   // called again before the page flip occurrs.
111   //
112   // Returns true if the page flip was successfully registered, false otherwise.
113   bool SchedulePageFlip();
114
115   // Called when the page flip event occurred. The event is provided by the
116   // kernel when a VBlank event finished. This allows the controller to
117   // update internal state and propagate the update to the surface.
118   // The tuple (seconds, useconds) represents the event timestamp. |seconds|
119   // represents the number of seconds while |useconds| represents the
120   // microseconds (< 1 second) in the timestamp.
121   void OnPageFlipEvent(unsigned int frame,
122                        unsigned int seconds,
123                        unsigned int useconds);
124
125   // Set the hardware cursor to show the contents of |surface|.
126   bool SetCursor(DriSurface* surface);
127
128   bool UnsetCursor();
129
130   // Moves the hardware cursor to |location|.
131   bool MoveCursor(const gfx::Point& location);
132
133   int get_fd() const { return drm_->get_fd(); };
134
135   const drmModeModeInfo& get_mode() const { return mode_; };
136   uint32_t connector_id() const { return connector_id_; }
137   uint32_t crtc_id() const { return crtc_id_; }
138   DriSurface* get_surface() const { return surface_.get(); };
139
140   uint64_t get_time_of_last_flip() const {
141     return time_of_last_flip_;
142   };
143
144  private:
145   bool RegisterFramebuffers(DriSurface* surface, drmModeModeInfo mode);
146   void UnregisterFramebuffers(DriSurface* surface);
147
148   // Object containing the connection to the graphics device and wraps the API
149   // calls to control it.
150   DriWrapper* drm_;
151
152   // TODO(dnicoara) Need to allow a CRTC to have multiple connectors.
153   uint32_t connector_id_;
154
155   uint32_t crtc_id_;
156
157   // TODO(dnicoara) Need to store all the modes.
158   drmModeModeInfo mode_;
159
160   scoped_ptr<DriSurface> surface_;
161
162   uint64_t time_of_last_flip_;
163
164   DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
165 };
166
167 }  // namespace ui
168
169 #endif  // UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_