Home | History | Annotate | Download | only in dri
      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 "base/memory/scoped_vector.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "ui/ozone/platform/dri/dri_wrapper.h"
     18 
     19 namespace gfx {
     20 class Point;
     21 }
     22 
     23 namespace ui {
     24 
     25 class CrtcState;
     26 class ScanoutBuffer;
     27 
     28 struct OverlayPlane {
     29   // Simpler constructor for the primary plane.
     30   explicit OverlayPlane(scoped_refptr<ScanoutBuffer> buffer);
     31 
     32   OverlayPlane(scoped_refptr<ScanoutBuffer> buffer,
     33                int z_order,
     34                gfx::OverlayTransform plane_transform,
     35                const gfx::Rect& display_bounds,
     36                const gfx::RectF& crop_rect);
     37 
     38   ~OverlayPlane();
     39 
     40   scoped_refptr<ScanoutBuffer> buffer;
     41   int z_order;
     42   gfx::OverlayTransform plane_transform;
     43   gfx::Rect display_bounds;
     44   gfx::RectF crop_rect;
     45   int overlay_plane;
     46 };
     47 
     48 typedef std::vector<OverlayPlane> OverlayPlaneList;
     49 
     50 // The HDCOz will handle modesettings and scannout operations for hardware
     51 // devices.
     52 //
     53 // In the DRM world there are 3 components that need to be paired up to be able
     54 // to display an image to the monitor: CRTC (cathode ray tube controller),
     55 // encoder and connector. The CRTC determines which framebuffer to read, when
     56 // to scanout and where to scanout. Encoders converts the stream from the CRTC
     57 // to the appropriate format for the connector. The connector is the physical
     58 // connection that monitors connect to.
     59 //
     60 // There is no 1:1:1 pairing for these components. It is possible for an encoder
     61 // to be compatible to multiple CRTCs and each connector can be used with
     62 // multiple encoders. In addition, it is possible to use one CRTC with multiple
     63 // connectors such that we can display the same image on multiple monitors.
     64 //
     65 // For example, the following configuration shows 2 different screens being
     66 // initialized separately.
     67 // -------------      -------------
     68 // | Connector |      | Connector |
     69 // |   HDMI    |      |    VGA    |
     70 // -------------      -------------
     71 //       ^                  ^
     72 //       |                  |
     73 // -------------      -------------
     74 // |  Encoder1  |     |  Encoder2 |
     75 // -------------      -------------
     76 //       ^                  ^
     77 //       |                  |
     78 // -------------      -------------
     79 // |   CRTC1   |      |   CRTC2   |
     80 // -------------      -------------
     81 //
     82 // In the following configuration 2 different screens are associated with the
     83 // same CRTC, so on scanout the same framebuffer will be displayed on both
     84 // monitors.
     85 // -------------      -------------
     86 // | Connector |      | Connector |
     87 // |   HDMI    |      |    VGA    |
     88 // -------------      -------------
     89 //       ^                  ^
     90 //       |                  |
     91 // -------------      -------------
     92 // |  Encoder1  |     |  Encoder2 |
     93 // -------------      -------------
     94 //       ^                  ^
     95 //       |                  |
     96 //      ----------------------
     97 //      |        CRTC1       |
     98 //      ----------------------
     99 //
    100 // Note that it is possible to have more connectors than CRTCs which means that
    101 // only a subset of connectors can be active independently, showing different
    102 // framebuffers. Though, in this case, it would be possible to have all
    103 // connectors active if some use the same CRTC to mirror the display.
    104 class HardwareDisplayController
    105     : public base::SupportsWeakPtr<HardwareDisplayController> {
    106  public:
    107   HardwareDisplayController(DriWrapper* drm,
    108                             scoped_ptr<CrtcState> state);
    109 
    110   ~HardwareDisplayController();
    111 
    112   // Performs the initial CRTC configuration. If successful, it will display the
    113   // framebuffer for |primary| with |mode|.
    114   bool Modeset(const OverlayPlane& primary,
    115                drmModeModeInfo mode);
    116 
    117   // Reconfigures the CRTC with the current surface and mode.
    118   bool Enable();
    119 
    120   // Disables the CRTC.
    121   void Disable();
    122 
    123   void QueueOverlayPlane(const OverlayPlane& plane);
    124 
    125   // Schedules the |overlays|' framebuffers to be displayed on the next vsync
    126   // event. The event will be posted on the graphics card file descriptor |fd_|
    127   // and it can be read and processed by |drmHandleEvent|. That function can
    128   // define the callback for the page flip event. A generic data argument will
    129   // be presented to the callback. We use that argument to pass in the HDCO
    130   // object the event belongs to.
    131   //
    132   // Between this call and the callback, the framebuffers used in this call
    133   // should not be modified in any way as it would cause screen tearing if the
    134   // hardware performed the flip. Note that the frontbuffer should also not
    135   // be modified as it could still be displayed.
    136   //
    137   // Note that this function does not block. Also, this function should not be
    138   // called again before the page flip occurrs.
    139   //
    140   // Returns true if the page flip was successfully registered, false otherwise.
    141   bool SchedulePageFlip();
    142 
    143   // TODO(dnicoara) This should be on the MessageLoop when Ozone can have
    144   // BeginFrame can be triggered explicitly by Ozone.
    145   void WaitForPageFlipEvent();
    146 
    147   // Called when the page flip event occurred. The event is provided by the
    148   // kernel when a VBlank event finished. This allows the controller to
    149   // update internal state and propagate the update to the surface.
    150   // The tuple (seconds, useconds) represents the event timestamp. |seconds|
    151   // represents the number of seconds while |useconds| represents the
    152   // microseconds (< 1 second) in the timestamp.
    153   void OnPageFlipEvent(unsigned int frame,
    154                        unsigned int seconds,
    155                        unsigned int useconds);
    156 
    157   // Set the hardware cursor to show the contents of |surface|.
    158   bool SetCursor(scoped_refptr<ScanoutBuffer> buffer);
    159 
    160   bool UnsetCursor();
    161 
    162   // Moves the hardware cursor to |location|.
    163   bool MoveCursor(const gfx::Point& location);
    164 
    165   void AddCrtc(scoped_ptr<CrtcState> state);
    166   scoped_ptr<CrtcState> RemoveCrtc(uint32_t crtc);
    167   bool HasCrtc(uint32_t crtc) const;
    168   bool IsMirrored() const;
    169   bool IsDisabled() const;
    170   gfx::Size GetModeSize() const;
    171 
    172   gfx::Point origin() const { return origin_; }
    173   void set_origin(const gfx::Point& origin) { origin_ = origin; }
    174 
    175   const drmModeModeInfo& get_mode() const { return mode_; };
    176   uint64_t get_time_of_last_flip() const {
    177     return time_of_last_flip_;
    178   };
    179 
    180  private:
    181   bool ModesetCrtc(const scoped_refptr<ScanoutBuffer>& buffer,
    182                    drmModeModeInfo mode,
    183                    CrtcState* state);
    184 
    185   bool SchedulePageFlipOnCrtc(const OverlayPlaneList& overlays,
    186                               CrtcState* state);
    187 
    188   // Buffers need to be declared first so that they are destroyed last. Needed
    189   // since the controllers may reference the buffers.
    190   OverlayPlaneList current_planes_;
    191   OverlayPlaneList pending_planes_;
    192   scoped_refptr<ScanoutBuffer> cursor_buffer_;
    193 
    194   // Object containing the connection to the graphics device and wraps the API
    195   // calls to control it.
    196   DriWrapper* drm_;
    197 
    198   // Stores the CRTC configuration. This is used to identify monitors and
    199   // configure them.
    200   ScopedVector<CrtcState> crtc_states_;
    201   gfx::Point origin_;
    202   drmModeModeInfo mode_;
    203   bool is_disabled_;
    204   uint64_t time_of_last_flip_;
    205 
    206   // Keeps track of the number of page flips scheduled but not yet serviced (in
    207   // mirror mode each CRTC schedules its own page flip event). This value is
    208   // changed as follows:
    209   //  1) incremented when a successful SchedulePageFlipOnController() occurrs,
    210   //  2) decremented when the page flip callback is triggered,
    211   //  3) reset to 0 when a drmModeSetCrtc is called (via the DriWrapper).
    212   uint32_t pending_page_flips_;
    213 
    214   DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
    215 };
    216 
    217 }  // namespace ui
    218 
    219 #endif  // UI_OZONE_PLATFORM_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
    220