1 #include <stdio.h> 2 #include <iostream> 3 #include <unistd.h> 4 #include <fcntl.h> 5 #include <cassert> 6 7 #include <kms++/kms++.h> 8 #include "helpers.h" 9 10 using namespace std; 11 12 namespace kms 13 { 14 15 struct CrtcPriv 16 { 17 drmModeCrtcPtr drm_crtc; 18 }; 19 20 Crtc::Crtc(Card &card, uint32_t id, uint32_t idx) 21 :DrmPropObject(card, id, DRM_MODE_OBJECT_CRTC, idx) 22 { 23 m_priv = new CrtcPriv(); 24 m_priv->drm_crtc = drmModeGetCrtc(this->card().fd(), this->id()); 25 assert(m_priv->drm_crtc); 26 } 27 28 Crtc::~Crtc() 29 { 30 drmModeFreeCrtc(m_priv->drm_crtc); 31 delete m_priv; 32 } 33 34 void Crtc::refresh() 35 { 36 drmModeFreeCrtc(m_priv->drm_crtc); 37 38 m_priv->drm_crtc = drmModeGetCrtc(this->card().fd(), this->id()); 39 assert(m_priv->drm_crtc); 40 } 41 42 void Crtc::setup() 43 { 44 for (Plane* plane : card().get_planes()) { 45 if (plane->supports_crtc(this)) 46 m_possible_planes.push_back(plane); 47 } 48 } 49 50 void Crtc::restore_mode(Connector* conn) 51 { 52 auto c = m_priv->drm_crtc; 53 54 uint32_t conns[] = { conn->id() }; 55 56 drmModeSetCrtc(card().fd(), id(), c->buffer_id, 57 c->x, c->y, 58 conns, 1, &c->mode); 59 } 60 61 int Crtc::set_mode(Connector* conn, const Videomode& mode) 62 { 63 AtomicReq req(card()); 64 65 unique_ptr<Blob> blob = mode.to_blob(card()); 66 67 req.add(conn, { 68 { "CRTC_ID", this->id() }, 69 }); 70 71 req.add(this, { 72 { "ACTIVE", 1 }, 73 { "MODE_ID", blob->id() }, 74 }); 75 76 int r = req.commit_sync(true); 77 78 refresh(); 79 80 return r; 81 } 82 83 int Crtc::set_mode(Connector* conn, Framebuffer& fb, const Videomode& mode) 84 { 85 uint32_t conns[] = { conn->id() }; 86 drmModeModeInfo drmmode = video_mode_to_drm_mode(mode); 87 88 return drmModeSetCrtc(card().fd(), id(), fb.id(), 89 0, 0, 90 conns, 1, &drmmode); 91 } 92 93 int Crtc::disable_mode() 94 { 95 return drmModeSetCrtc(card().fd(), id(), 0, 0, 0, 0, 0, 0); 96 } 97 98 static inline uint32_t conv(float x) 99 { 100 // XXX fix the conversion for fractional part 101 return ((uint32_t)x) << 16; 102 } 103 104 int Crtc::set_plane(Plane* plane, Framebuffer& fb, 105 int32_t dst_x, int32_t dst_y, uint32_t dst_w, uint32_t dst_h, 106 float src_x, float src_y, float src_w, float src_h) 107 { 108 return drmModeSetPlane(card().fd(), plane->id(), id(), fb.id(), 0, 109 dst_x, dst_y, dst_w, dst_h, 110 conv(src_x), conv(src_y), conv(src_w), conv(src_h)); 111 } 112 113 int Crtc::disable_plane(Plane* plane) 114 { 115 return drmModeSetPlane(card().fd(), plane->id(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 116 } 117 118 Plane* Crtc::get_primary_plane() 119 { 120 Plane *primary = nullptr; 121 122 for (Plane* p : get_possible_planes()) { 123 if (p->plane_type() != PlaneType::Primary) 124 continue; 125 126 if (p->crtc_id() == id()) 127 return p; 128 129 primary = p; 130 } 131 132 if (primary) 133 return primary; 134 135 throw invalid_argument(string("No primary plane for crtc ") + to_string(id())); 136 } 137 138 int Crtc::page_flip(Framebuffer& fb, void *data) 139 { 140 return drmModePageFlip(card().fd(), id(), fb.id(), DRM_MODE_PAGE_FLIP_EVENT, data); 141 } 142 143 uint32_t Crtc::buffer_id() const 144 { 145 return m_priv->drm_crtc->buffer_id; 146 } 147 148 uint32_t Crtc::x() const 149 { 150 return m_priv->drm_crtc->x; 151 } 152 153 uint32_t Crtc::y() const 154 { 155 return m_priv->drm_crtc->y; 156 } 157 158 uint32_t Crtc::width() const 159 { 160 return m_priv->drm_crtc->width; 161 } 162 163 uint32_t Crtc::height() const 164 { 165 return m_priv->drm_crtc->height; 166 } 167 168 int Crtc::mode_valid() const 169 { 170 return m_priv->drm_crtc->mode_valid; 171 } 172 173 Videomode Crtc::mode() const 174 { 175 return drm_mode_to_video_mode(m_priv->drm_crtc->mode); 176 } 177 178 int Crtc::gamma_size() const 179 { 180 return m_priv->drm_crtc->gamma_size; 181 } 182 183 } 184