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 25using 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 36ScreenManager* gScreenManager; 37 38 39class ScreenChangeListener : public HWInterfaceListener { 40public: 41 ScreenChangeListener(ScreenManager& manager, 42 Screen* screen); 43 44private: 45virtual void ScreenChanged(HWInterface* interface); 46 47 ScreenManager& fManager; 48 Screen* fScreen; 49}; 50 51 52ScreenChangeListener::ScreenChangeListener(ScreenManager& manager, 53 Screen* screen) 54 : 55 fManager(manager), 56 fScreen(screen) 57{ 58} 59 60 61void 62ScreenChangeListener::ScreenChanged(HWInterface* interface) 63{ 64 fManager.ScreenChanged(fScreen); 65} 66 67 68ScreenManager::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 91ScreenManager::~ScreenManager() 92{ 93} 94 95 96Screen* 97ScreenManager::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 110int32 111ScreenManager::CountScreens() const 112{ 113 if (!IsLocked()) 114 debugger("Called ScreenManager::CountScreens() without lock!"); 115 116 return fScreenList.CountItems(); 117} 118 119 120status_t 121ScreenManager::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 161void 162ScreenManager::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 179void 180ScreenManager::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 192void 193ScreenManager::_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 216ScreenManager::screen_item* 217ScreenManager::_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 252void 253ScreenManager::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