xref: /haiku/src/servers/app/ScreenManager.cpp (revision c9ad965c81b08802fed0827fd1dd16f45297928a)
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 "remote/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 ScreenManager::ScreenManager()
40 	:
41 	BLooper("screen manager"),
42 	fScreenList(4)
43 {
44 	_ScanDrivers();
45 
46 	// turn on node monitoring the graphics driver directory
47 	BEntry entry("/dev/graphics");
48 	node_ref nodeRef;
49 	if (entry.InitCheck() == B_OK && entry.GetNodeRef(&nodeRef) == B_OK)
50 		watch_node(&nodeRef, B_WATCH_DIRECTORY, this);
51 }
52 
53 
54 ScreenManager::~ScreenManager()
55 {
56 	for (int32 i = 0; i < fScreenList.CountItems(); i++) {
57 		screen_item* item = fScreenList.ItemAt(i);
58 
59 		delete item->screen;
60 		delete item;
61 	}
62 }
63 
64 
65 Screen*
66 ScreenManager::ScreenAt(int32 index) const
67 {
68 	if (!IsLocked())
69 		debugger("Called ScreenManager::ScreenAt() without lock!");
70 
71 	screen_item* item = fScreenList.ItemAt(index);
72 	if (item != NULL)
73 		return item->screen;
74 
75 	return NULL;
76 }
77 
78 
79 int32
80 ScreenManager::CountScreens() const
81 {
82 	if (!IsLocked())
83 		debugger("Called ScreenManager::CountScreens() without lock!");
84 
85 	return fScreenList.CountItems();
86 }
87 
88 
89 status_t
90 ScreenManager::AcquireScreens(ScreenOwner* owner, int32* wishList,
91 	int32 wishCount, const char* target, bool force, ScreenList& list)
92 {
93 	BAutolock locker(this);
94 	int32 added = 0;
95 
96 	// TODO: don't ignore the wish list
97 
98 	for (int32 i = 0; i < fScreenList.CountItems(); i++) {
99 		screen_item* item = fScreenList.ItemAt(i);
100 
101 		if (item->owner == NULL && list.AddItem(item->screen)) {
102 			item->owner = owner;
103 			added++;
104 		}
105 	}
106 
107 #if TEST_MODE == 0
108 	if (added == 0 && target != NULL) {
109 		// there's a specific target screen we want to initialize
110 		// TODO: right now we only support remote screens, but we could
111 		// also target specific accelerants to support other graphics cards
112 		RemoteHWInterface* interface = new(nothrow) RemoteHWInterface(target);
113 		if (interface != NULL) {
114 			screen_item* item = _AddHWInterface(interface);
115 			if (item != NULL && list.AddItem(item->screen)) {
116 				item->owner = owner;
117 				added++;
118 			}
119 		}
120 	}
121 #endif // TEST_MODE == 0
122 
123 	return added > 0 ? B_OK : B_ENTRY_NOT_FOUND;
124 }
125 
126 
127 void
128 ScreenManager::ReleaseScreens(ScreenList& list)
129 {
130 	BAutolock locker(this);
131 
132 	for (int32 i = 0; i < fScreenList.CountItems(); i++) {
133 		screen_item* item = fScreenList.ItemAt(i);
134 
135 		for (int32 j = 0; j < list.CountItems(); j++) {
136 			Screen* screen = list.ItemAt(j);
137 
138 			if (item->screen == screen)
139 				item->owner = NULL;
140 		}
141 	}
142 }
143 
144 
145 void
146 ScreenManager::_ScanDrivers()
147 {
148 	HWInterface* interface = NULL;
149 
150 	// Eventually we will loop through drivers until
151 	// one can't initialize in order to support multiple monitors.
152 	// For now, we'll just load one and be done with it.
153 
154 	// ToDo: to make monitoring the driver directory useful, we need more
155 	//	power and data here, and should do the scanning on our own
156 
157 	bool initDrivers = true;
158 	while (initDrivers) {
159 
160 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
161 		  interface = new AccelerantHWInterface();
162 #elif defined(USE_DIRECT_WINDOW_TEST_MODE)
163 		  interface = new DWindowHWInterface();
164 #else
165 		  interface = new ViewHWInterface();
166 #endif
167 
168 		_AddHWInterface(interface);
169 		initDrivers = false;
170 	}
171 }
172 
173 
174 ScreenManager::screen_item*
175 ScreenManager::_AddHWInterface(HWInterface* interface)
176 {
177 	Screen* screen = new(nothrow) Screen(interface, fScreenList.CountItems());
178 	if (screen == NULL) {
179 		delete interface;
180 		return NULL;
181 	}
182 
183 	// The interface is now owned by the screen
184 
185 	if (screen->Initialize() >= B_OK) {
186 		screen_item* item = new(nothrow) screen_item;
187 		if (item != NULL) {
188 			item->screen = screen;
189 			item->owner = NULL;
190 			if (fScreenList.AddItem(item))
191 				return item;
192 
193 			delete item;
194 		}
195 	}
196 
197 	delete screen;
198 	return NULL;
199 }
200 
201 
202 void
203 ScreenManager::MessageReceived(BMessage* message)
204 {
205 	switch (message->what) {
206 		case B_NODE_MONITOR:
207 			// TODO: handle notification
208 			break;
209 
210 		default:
211 			BHandler::MessageReceived(message);
212 	}
213 }
214 
215