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.
5 #ifndef UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
6 #define UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
10 #include <xf86drmMode.h>
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"
26 // The HDCOz will handle modesettings and scannout operations for hardware
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.
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.
41 // For example, the following configuration shows 2 different screens being
42 // initialized separately.
43 // ------------- -------------
44 // | Connector | | Connector |
46 // ------------- -------------
49 // ------------- -------------
50 // | Encoder1 | | Encoder2 |
51 // ------------- -------------
54 // ------------- -------------
55 // | CRTC1 | | CRTC2 |
56 // ------------- -------------
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
61 // ------------- -------------
62 // | Connector | | Connector |
64 // ------------- -------------
67 // ------------- -------------
68 // | Encoder1 | | Encoder2 |
69 // ------------- -------------
72 // ----------------------
74 // ----------------------
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.
81 // TODO(dnicoara) Need to have a way to detect events (such as monitor
82 // connected or disconnected).
83 class OZONE_EXPORT HardwareDisplayController {
85 HardwareDisplayController(DriWrapper* drm,
86 uint32_t connector_id,
89 ~HardwareDisplayController();
91 // Associate the HDCO with a surface implementation and initialize it.
92 bool BindSurfaceToController(scoped_ptr<DriSurface> surface,
93 drmModeModeInfo mode);
95 void UnbindSurfaceFromController();
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.
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.
109 // Note that this function does not block. Also, this function should not be
110 // called again before the page flip occurrs.
112 // Returns true if the page flip was successfully registered, false otherwise.
113 bool SchedulePageFlip();
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);
125 // Set the hardware cursor to show the contents of |surface|.
126 bool SetCursor(DriSurface* surface);
130 // Moves the hardware cursor to |location|.
131 bool MoveCursor(const gfx::Point& location);
133 int get_fd() const { return drm_->get_fd(); };
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(); };
140 uint64_t get_time_of_last_flip() const {
141 return time_of_last_flip_;
145 bool RegisterFramebuffers(DriSurface* surface, drmModeModeInfo mode);
146 void UnregisterFramebuffers(DriSurface* surface);
148 // Object containing the connection to the graphics device and wraps the API
149 // calls to control it.
152 // TODO(dnicoara) Need to allow a CRTC to have multiple connectors.
153 uint32_t connector_id_;
157 // TODO(dnicoara) Need to store all the modes.
158 drmModeModeInfo mode_;
160 scoped_ptr<DriSurface> surface_;
162 uint64_t time_of_last_flip_;
164 DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
169 #endif // UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_