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
ScreenChangeListener(ScreenManager & manager,Screen * screen)52 ScreenChangeListener::ScreenChangeListener(ScreenManager& manager,
53 Screen* screen)
54 :
55 fManager(manager),
56 fScreen(screen)
57 {
58 }
59
60
61 void
ScreenChanged(HWInterface * interface)62 ScreenChangeListener::ScreenChanged(HWInterface* interface)
63 {
64 fManager.ScreenChanged(fScreen);
65 }
66
67
ScreenManager()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
~ScreenManager()91 ScreenManager::~ScreenManager()
92 {
93 }
94
95
96 Screen*
ScreenAt(int32 index) const97 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
CountScreens() const111 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
AcquireScreens(ScreenOwner * owner,int32 * wishList,int32 wishCount,const char * target,bool force,ScreenList & list)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
ReleaseScreens(ScreenList & list)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
ScreenChanged(Screen * screen)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
_ScanDrivers()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*
_AddHWInterface(HWInterface * interface)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
MessageReceived(BMessage * message)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