1 /* 2 * Copyright 2005-2009, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 /** Manages all available physical screens */ 10 11 12 #include "ScreenManager.h" 13 14 #include "Screen.h" 15 #include "ServerConfig.h" 16 17 #include "RemoteHWInterface.h" 18 19 #include <Autolock.h> 20 #include <Entry.h> 21 #include <NodeMonitor.h> 22 23 #include <new> 24 25 using std::nothrow; 26 27 28 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 29 # include "AccelerantHWInterface.h" 30 #else 31 # include "ViewHWInterface.h" 32 # include "DWindowHWInterface.h" 33 #endif 34 35 36 ScreenManager* gScreenManager; 37 38 39 class ScreenChangeListener : public HWInterfaceListener { 40 public: 41 ScreenChangeListener(ScreenManager& manager, 42 Screen* screen); 43 44 private: 45 virtual void ScreenChanged(HWInterface* interface); 46 47 ScreenManager& fManager; 48 Screen* fScreen; 49 }; 50 51 52 ScreenChangeListener::ScreenChangeListener(ScreenManager& manager, 53 Screen* screen) 54 : 55 fManager(manager), 56 fScreen(screen) 57 { 58 } 59 60 61 void 62 ScreenChangeListener::ScreenChanged(HWInterface* interface) 63 { 64 fManager.ScreenChanged(fScreen); 65 } 66 67 68 ScreenManager::ScreenManager() 69 : 70 BLooper("screen manager"), 71 fScreenList(4, true) 72 { 73 #ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST 74 # if defined(USE_DIRECT_WINDOW_TEST_MODE) 75 _AddHWInterface(new DWindowHWInterface()); 76 # else 77 _AddHWInterface(new ViewHWInterface()); 78 # endif 79 #else 80 _ScanDrivers(); 81 82 // turn on node monitoring the graphics driver directory 83 BEntry entry("/dev/graphics"); 84 node_ref nodeRef; 85 if (entry.InitCheck() == B_OK && entry.GetNodeRef(&nodeRef) == B_OK) 86 watch_node(&nodeRef, B_WATCH_DIRECTORY, this); 87 #endif 88 } 89 90 91 ScreenManager::~ScreenManager() 92 { 93 } 94 95 96 Screen* 97 ScreenManager::ScreenAt(int32 index) const 98 { 99 if (!IsLocked()) 100 debugger("Called ScreenManager::ScreenAt() without lock!"); 101 102 screen_item* item = fScreenList.ItemAt(index); 103 if (item != NULL) 104 return item->screen.Get(); 105 106 return NULL; 107 } 108 109 110 int32 111 ScreenManager::CountScreens() const 112 { 113 if (!IsLocked()) 114 debugger("Called ScreenManager::CountScreens() without lock!"); 115 116 return fScreenList.CountItems(); 117 } 118 119 120 status_t 121 ScreenManager::AcquireScreens(ScreenOwner* owner, int32* wishList, 122 int32 wishCount, const char* target, bool force, ScreenList& list) 123 { 124 BAutolock locker(this); 125 int32 added = 0; 126 127 // TODO: don't ignore the wish list 128 129 for (int32 i = 0; i < fScreenList.CountItems(); i++) { 130 screen_item* item = fScreenList.ItemAt(i); 131 132 if (item->owner == NULL && list.AddItem(item->screen.Get())) { 133 item->owner = owner; 134 added++; 135 } 136 } 137 138 if (added == 0 && target != NULL) { 139 // there's a specific target screen we want to initialize 140 // TODO: right now we only support remote screens, but we could 141 // also target specific accelerants to support other graphics cards 142 HWInterface* interface; 143 #ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST 144 interface = new(nothrow) ViewHWInterface(); 145 #else 146 interface = new(nothrow) RemoteHWInterface(target); 147 #endif 148 if (interface != NULL) { 149 screen_item* item = _AddHWInterface(interface); 150 if (item != NULL && list.AddItem(item->screen.Get())) { 151 item->owner = owner; 152 added++; 153 } 154 } 155 } 156 157 return added > 0 ? B_OK : B_ENTRY_NOT_FOUND; 158 } 159 160 161 void 162 ScreenManager::ReleaseScreens(ScreenList& list) 163 { 164 BAutolock locker(this); 165 166 for (int32 i = 0; i < fScreenList.CountItems(); i++) { 167 screen_item* item = fScreenList.ItemAt(i); 168 169 for (int32 j = 0; j < list.CountItems(); j++) { 170 Screen* screen = list.ItemAt(j); 171 172 if (item->screen.Get() == screen) 173 item->owner = NULL; 174 } 175 } 176 } 177 178 179 void 180 ScreenManager::ScreenChanged(Screen* screen) 181 { 182 BAutolock locker(this); 183 184 for (int32 i = 0; i < fScreenList.CountItems(); i++) { 185 screen_item* item = fScreenList.ItemAt(i); 186 if (item->screen.Get() == screen) 187 item->owner->ScreenChanged(screen); 188 } 189 } 190 191 192 void 193 ScreenManager::_ScanDrivers() 194 { 195 HWInterface* interface = NULL; 196 197 // Eventually we will loop through drivers until 198 // one can't initialize in order to support multiple monitors. 199 // For now, we'll just load one and be done with it. 200 201 // ToDo: to make monitoring the driver directory useful, we need more 202 // power and data here, and should do the scanning on our own 203 204 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 205 bool initDrivers = true; 206 while (initDrivers) { 207 interface = new AccelerantHWInterface(); 208 209 _AddHWInterface(interface); 210 initDrivers = false; 211 } 212 #endif 213 } 214 215 216 ScreenManager::screen_item* 217 ScreenManager::_AddHWInterface(HWInterface* interface) 218 { 219 ObjectDeleter<Screen> screen( 220 new(nothrow) Screen(interface, fScreenList.CountItems())); 221 if (!screen.IsSet()) { 222 delete interface; 223 return NULL; 224 } 225 226 // The interface is now owned by the screen 227 228 if (screen->Initialize() >= B_OK) { 229 screen_item* item = new(nothrow) screen_item; 230 231 if (item != NULL) { 232 item->screen.SetTo(screen.Detach()); 233 item->owner = NULL; 234 item->listener.SetTo( 235 new(nothrow) ScreenChangeListener(*this, item->screen.Get())); 236 if (item->listener.IsSet() 237 && interface->AddListener(item->listener.Get())) { 238 if (fScreenList.AddItem(item)) 239 return item; 240 241 interface->RemoveListener(item->listener.Get()); 242 } 243 244 delete item; 245 } 246 } 247 248 return NULL; 249 } 250 251 252 void 253 ScreenManager::MessageReceived(BMessage* message) 254 { 255 switch (message->what) { 256 case B_NODE_MONITOR: 257 // TODO: handle notification 258 break; 259 260 default: 261 BHandler::MessageReceived(message); 262 } 263 } 264