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 #include "ui/gfx/ozone/dri/hardware_display_controller.h" 6 7 #include <errno.h> 8 #include <string.h> 9 10 #include "base/basictypes.h" 11 #include "base/logging.h" 12 #include "base/time/time.h" 13 #include "ui/gfx/ozone/dri/dri_skbitmap.h" 14 #include "ui/gfx/ozone/dri/dri_surface.h" 15 #include "ui/gfx/ozone/dri/dri_wrapper.h" 16 17 namespace gfx { 18 19 HardwareDisplayController::HardwareDisplayController() 20 : drm_(NULL), 21 connector_id_(0), 22 crtc_id_(0), 23 mode_(), 24 saved_crtc_(NULL), 25 state_(UNASSOCIATED), 26 surface_(), 27 time_of_last_flip_(0) {} 28 29 void HardwareDisplayController::SetControllerInfo( 30 DriWrapper* drm, 31 uint32_t connector_id, 32 uint32_t crtc_id, 33 uint32_t dpms_property_id, 34 drmModeModeInfo mode) { 35 drm_ = drm; 36 connector_id_ = connector_id; 37 crtc_id_ = crtc_id; 38 dpms_property_id_ = dpms_property_id; 39 mode_ = mode; 40 saved_crtc_ = drm_->GetCrtc(crtc_id_); 41 state_ = UNINITIALIZED; 42 } 43 44 HardwareDisplayController::~HardwareDisplayController() { 45 if (saved_crtc_) { 46 if (!drm_->SetCrtc(saved_crtc_, &connector_id_)) 47 DLOG(ERROR) << "Failed to restore CRTC state: " << strerror(errno); 48 drm_->FreeCrtc(saved_crtc_); 49 } 50 51 if (surface_.get()) { 52 // Unregister the buffers. 53 for (int i = 0; i < 2; ++i) { 54 if (!drm_->RemoveFramebuffer(surface_->bitmaps_[i]->get_framebuffer())) 55 DLOG(ERROR) << "Failed to remove FB: " << strerror(errno); 56 } 57 } 58 } 59 60 bool 61 HardwareDisplayController::BindSurfaceToController( 62 scoped_ptr<DriSurface> surface) { 63 CHECK(state_ == UNINITIALIZED); 64 65 // Register the buffers. 66 for (int i = 0; i < 2; ++i) { 67 uint32_t fb_id; 68 if (!drm_->AddFramebuffer(mode_, 69 surface->bitmaps_[i]->GetColorDepth(), 70 surface->bitmaps_[i]->bytesPerPixel() << 3, 71 surface->bitmaps_[i]->rowBytes(), 72 surface->bitmaps_[i]->get_handle(), 73 &fb_id)) { 74 DLOG(ERROR) << "Failed to register framebuffer: " << strerror(errno); 75 state_ = FAILED; 76 return false; 77 } 78 surface->bitmaps_[i]->set_framebuffer(fb_id); 79 } 80 81 surface_.reset(surface.release()); 82 state_ = SURFACE_INITIALIZED; 83 return true; 84 } 85 86 bool HardwareDisplayController::SchedulePageFlip() { 87 CHECK(state_ == SURFACE_INITIALIZED || state_ == INITIALIZED); 88 89 if (state_ == SURFACE_INITIALIZED) { 90 // Perform the initial modeset. 91 if (!drm_->SetCrtc(crtc_id_, 92 surface_->GetFramebufferId(), 93 &connector_id_, 94 &mode_)) { 95 DLOG(ERROR) << "Cannot set CRTC: " << strerror(errno); 96 state_ = FAILED; 97 return false; 98 } else { 99 state_ = INITIALIZED; 100 } 101 102 if (dpms_property_id_) 103 drm_->ConnectorSetProperty(connector_id_, 104 dpms_property_id_, 105 DRM_MODE_DPMS_ON); 106 } 107 108 if (!drm_->PageFlip(crtc_id_, 109 surface_->GetFramebufferId(), 110 this)) { 111 state_ = FAILED; 112 LOG(ERROR) << "Cannot page flip: " << strerror(errno); 113 return false; 114 } 115 116 return true; 117 } 118 119 void HardwareDisplayController::OnPageFlipEvent(unsigned int frame, 120 unsigned int seconds, 121 unsigned int useconds) { 122 time_of_last_flip_ = 123 static_cast<uint64_t>(seconds) * base::Time::kMicrosecondsPerSecond + 124 useconds; 125 126 surface_->SwapBuffers(); 127 } 128 129 } // namespace gfx 130