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 #include "ui/ozone/platform/dri/screen_manager.h" 6 7 #include <xf86drmMode.h> 8 9 #include "ui/gfx/geometry/point.h" 10 #include "ui/gfx/geometry/rect.h" 11 #include "ui/gfx/geometry/size.h" 12 #include "ui/ozone/platform/dri/dri_util.h" 13 #include "ui/ozone/platform/dri/hardware_display_controller.h" 14 #include "ui/ozone/platform/dri/scanout_surface.h" 15 16 namespace ui { 17 18 ScreenManager::ScreenManager( 19 DriWrapper* dri, ScanoutSurfaceGenerator* surface_generator) 20 : dri_(dri), surface_generator_(surface_generator), last_added_widget_(0) { 21 } 22 23 ScreenManager::~ScreenManager() { 24 STLDeleteContainerPairSecondPointers( 25 controllers_.begin(), controllers_.end()); 26 } 27 28 void ScreenManager::RemoveDisplayController(uint32_t crtc, uint32_t connector) { 29 HardwareDisplayControllerMap::iterator it = 30 FindDisplayController(crtc, connector); 31 if (it != controllers_.end()) { 32 delete it->second; 33 controllers_.erase(it); 34 } 35 } 36 37 bool ScreenManager::ConfigureDisplayController(uint32_t crtc, 38 uint32_t connector, 39 const drmModeModeInfo& mode) { 40 HardwareDisplayControllerMap::iterator it = 41 FindDisplayController(crtc, connector); 42 HardwareDisplayController* controller = NULL; 43 if (it != controllers_.end()) { 44 if (SameMode(mode, it->second->get_mode())) 45 return it->second->Enable(); 46 47 controller = it->second; 48 controller->UnbindSurfaceFromController(); 49 } 50 51 if (it == controllers_.end()) { 52 controller = new HardwareDisplayController(dri_, connector, crtc); 53 controllers_.insert(std::make_pair(++last_added_widget_, controller)); 54 } 55 56 // Create a surface suitable for the current controller. 57 scoped_ptr<ScanoutSurface> surface( 58 surface_generator_->Create(gfx::Size(mode.hdisplay, mode.vdisplay))); 59 60 if (!surface->Initialize()) { 61 LOG(ERROR) << "Failed to initialize surface"; 62 return false; 63 } 64 65 // Bind the surface to the controller. This will register the backing buffers 66 // with the hardware CRTC such that we can show the buffers and performs the 67 // initial modeset. The controller takes ownership of the surface. 68 if (!controller->BindSurfaceToController(surface.Pass(), mode)) { 69 LOG(ERROR) << "Failed to bind surface to controller"; 70 return false; 71 } 72 73 return true; 74 } 75 76 bool ScreenManager::DisableDisplayController(uint32_t crtc, 77 uint32_t connector) { 78 HardwareDisplayControllerMap::iterator it = 79 FindDisplayController(crtc, connector); 80 if (it != controllers_.end()) { 81 it->second->Disable(); 82 return true; 83 } 84 85 return false; 86 } 87 88 base::WeakPtr<HardwareDisplayController> ScreenManager::GetDisplayController( 89 gfx::AcceleratedWidget widget) { 90 // TODO(dnicoara): Remove hack once TestScreen uses a simple Ozone display 91 // configuration reader and ScreenManager is called from there to create the 92 // one display needed by the content_shell target. 93 if (controllers_.empty() && last_added_widget_ == 0) 94 ForceInitializationOfPrimaryDisplay(); 95 96 HardwareDisplayControllerMap::iterator it = controllers_.find(widget); 97 if (it != controllers_.end()) 98 return it->second->AsWeakPtr(); 99 100 return base::WeakPtr<HardwareDisplayController>(); 101 } 102 103 ScreenManager::HardwareDisplayControllerMap::iterator 104 ScreenManager::FindDisplayController(uint32_t crtc, uint32_t connector) { 105 for (HardwareDisplayControllerMap::iterator it = controllers_.begin(); 106 it != controllers_.end(); 107 ++it) { 108 if (it->second->connector_id() == connector && 109 it->second->crtc_id() == crtc) 110 return it; 111 } 112 113 return controllers_.end(); 114 } 115 116 void ScreenManager::ForceInitializationOfPrimaryDisplay() { 117 drmModeRes* resources = drmModeGetResources(dri_->get_fd()); 118 DCHECK(resources) << "Failed to get DRM resources"; 119 ScopedVector<HardwareDisplayControllerInfo> displays = 120 GetAvailableDisplayControllerInfos(dri_->get_fd(), resources); 121 drmModeFreeResources(resources); 122 123 CHECK_NE(0u, displays.size()); 124 125 drmModePropertyRes* dpms = 126 dri_->GetProperty(displays[0]->connector(), "DPMS"); 127 if (dpms) 128 dri_->SetProperty(displays[0]->connector()->connector_id, 129 dpms->prop_id, 130 DRM_MODE_DPMS_ON); 131 132 ConfigureDisplayController(displays[0]->crtc()->crtc_id, 133 displays[0]->connector()->connector_id, 134 displays[0]->connector()->modes[0]); 135 } 136 137 } // namespace ui 138