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