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