Home | History | Annotate | Download | only in dri
      1 // Copyright 2013 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_GFX_OZONE_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
      6 #define UI_GFX_OZONE_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/gfx/gfx_export.h"
     16 #include "ui/gfx/ozone/dri/dri_wrapper.h"
     17 
     18 namespace gfx {
     19 
     20 class DriSurface;
     21 
     22 // The HDCOz will handle modesettings and scannout operations for hardware
     23 // devices.
     24 //
     25 // In the DRM world there are 3 components that need to be paired up to be able
     26 // to display an image to the monitor: CRTC (cathode ray tube controller),
     27 // encoder and connector. The CRTC determines which framebuffer to read, when
     28 // to scanout and where to scanout. Encoders converts the stream from the CRTC
     29 // to the appropriate format for the connector. The connector is the physical
     30 // connection that monitors connect to.
     31 //
     32 // There is no 1:1:1 pairing for these components. It is possible for an encoder
     33 // to be compatible to multiple CRTCs and each connector can be used with
     34 // multiple encoders. In addition, it is possible to use one CRTC with multiple
     35 // connectors such that we can display the same image on multiple monitors.
     36 //
     37 // For example, the following configuration shows 2 different screens being
     38 // initialized separately.
     39 // -------------      -------------
     40 // | Connector |      | Connector |
     41 // |   HDMI    |      |    VGA    |
     42 // -------------      -------------
     43 //       ^                  ^
     44 //       |                  |
     45 // -------------      -------------
     46 // |  Encoder1  |     |  Encoder2 |
     47 // -------------      -------------
     48 //       ^                  ^
     49 //       |                  |
     50 // -------------      -------------
     51 // |   CRTC1   |      |   CRTC2   |
     52 // -------------      -------------
     53 //
     54 // In the following configuration 2 different screens are associated with the
     55 // same CRTC, so on scanout the same framebuffer will be displayed on both
     56 // monitors.
     57 // -------------      -------------
     58 // | Connector |      | Connector |
     59 // |   HDMI    |      |    VGA    |
     60 // -------------      -------------
     61 //       ^                  ^
     62 //       |                  |
     63 // -------------      -------------
     64 // |  Encoder1  |     |  Encoder2 |
     65 // -------------      -------------
     66 //       ^                  ^
     67 //       |                  |
     68 //      ----------------------
     69 //      |        CRTC1       |
     70 //      ----------------------
     71 //
     72 // Note that it is possible to have more connectors than CRTCs which means that
     73 // only a subset of connectors can be active independently, showing different
     74 // framebuffers. Though, in this case, it would be possible to have all
     75 // connectors active if some use the same CRTC to mirror the display.
     76 //
     77 // TODO(dnicoara) Need to have a way to detect events (such as monitor
     78 // connected or disconnected).
     79 class GFX_EXPORT HardwareDisplayController {
     80  public:
     81   // Controller states. The state transitions will happen from top to bottom.
     82   enum State {
     83     // When we allocate a HDCO as a stub. At this point there is no connector
     84     // and CRTC associated with this device.
     85     UNASSOCIATED,
     86 
     87     // When |SetControllerInfo| is called and the HDCO has the information of
     88     // the hardware it will control. At this point it knows everything it needs
     89     // to control the hardware but doesn't have a surface.
     90     UNINITIALIZED,
     91 
     92     // A surface is associated with the HDCO. This means that the controller can
     93     // potentially display the backing surface to the display. Though the
     94     // surface framebuffer still needs to be registered with the CRTC.
     95     SURFACE_INITIALIZED,
     96 
     97     // The CRTC now knows about the surface attributes.
     98     INITIALIZED,
     99 
    100     // Error state if any of the initialization steps fail.
    101     FAILED,
    102   };
    103 
    104   HardwareDisplayController();
    105 
    106   ~HardwareDisplayController();
    107 
    108   // Set the hardware configuration for this HDCO. Once this is set, the HDCO is
    109   // responsible for keeping track of the connector and CRTC and cleaning up
    110   // when it is destroyed.
    111   void SetControllerInfo(DriWrapper* drm,
    112                          uint32_t connector_id,
    113                          uint32_t crtc_id,
    114                          uint32_t dpms_property_id,
    115                          drmModeModeInfo mode);
    116 
    117   // Associate the HDCO with a surface implementation and initialize it.
    118   bool BindSurfaceToController(scoped_ptr<DriSurface> surface);
    119 
    120   // Schedules the |surface_|'s framebuffer to be displayed on the next vsync
    121   // event. The event will be posted on the graphics card file descriptor |fd_|
    122   // and it can be read and processed by |drmHandleEvent|. That function can
    123   // define the callback for the page flip event. A generic data argument will
    124   // be presented to the callback. We use that argument to pass in the HDCO
    125   // object the event belongs to.
    126   //
    127   // Between this call and the callback, the framebuffer used in this call
    128   // should not be modified in any way as it would cause screen tearing if the
    129   // hardware performed the flip. Note that the frontbuffer should also not
    130   // be modified as it could still be displayed.
    131   //
    132   // Note that this function does not block. Also, this function should not be
    133   // called again before the page flip occurrs.
    134   //
    135   // Returns true if the page flip was successfully registered, false otherwise.
    136   bool SchedulePageFlip();
    137 
    138   // Called when the page flip event occurred. The event is provided by the
    139   // kernel when a VBlank event finished. This allows the controller to
    140   // update internal state and propagate the update to the surface.
    141   // The tuple (seconds, useconds) represents the event timestamp. |seconds|
    142   // represents the number of seconds while |useconds| represents the
    143   // microseconds (< 1 second) in the timestamp.
    144   void OnPageFlipEvent(unsigned int frame,
    145                        unsigned int seconds,
    146                        unsigned int useconds);
    147 
    148   State get_state() const { return state_; };
    149 
    150   int get_fd() const { return drm_->get_fd(); };
    151 
    152   const drmModeModeInfo& get_mode() const { return mode_; };
    153 
    154   DriSurface* get_surface() const { return surface_.get(); };
    155 
    156   uint64_t get_time_of_last_flip() const {
    157     return time_of_last_flip_;
    158   };
    159 
    160  private:
    161   // Object containing the connection to the graphics device and wraps the API
    162   // calls to control it.
    163   DriWrapper* drm_;
    164 
    165   // TODO(dnicoara) Need to allow a CRTC to have multiple connectors.
    166   uint32_t connector_id_;
    167 
    168   uint32_t crtc_id_;
    169 
    170   uint32_t dpms_property_id_;
    171 
    172   // TODO(dnicoara) Need to store all the modes.
    173   drmModeModeInfo mode_;
    174 
    175   // Saved CRTC state from before we used it. Need it to restore state once we
    176   // are finished using this device.
    177   drmModeCrtc* saved_crtc_;
    178 
    179   State state_;
    180 
    181   scoped_ptr<DriSurface> surface_;
    182 
    183   uint64_t time_of_last_flip_;
    184 
    185   DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
    186 };
    187 
    188 }  // namespace gfx
    189 
    190 #endif  // UI_GFX_OZONE_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
    191