xref: /haiku/src/kits/interface/PrivateScreen.cpp (revision 5ec797a76f3bbb8ac83678bd568cee1d2e767d86)
1a817d6adSAxel Dörfler /*
257a6c095SAxel Dörfler  * Copyright 2002-2006, Haiku Inc.
3a817d6adSAxel Dörfler  * Distributed under the terms of the MIT License.
4a817d6adSAxel Dörfler  *
5a817d6adSAxel Dörfler  * Authors:
6a817d6adSAxel Dörfler  *		Stefano Ceccherini (burton666@libero.it)
7a817d6adSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
8a817d6adSAxel Dörfler  */
9a817d6adSAxel Dörfler 
1057a6c095SAxel Dörfler /*!
1157a6c095SAxel Dörfler 	BPrivateScreen is the class which does the real work for
1257a6c095SAxel Dörfler 	the proxy class BScreen (it interacts with the app_server).
13a817d6adSAxel Dörfler */
14a817d6adSAxel Dörfler 
15a817d6adSAxel Dörfler 
16d9525baaSAxel Dörfler #include "AppMisc.h"
17466871ccSAxel Dörfler #include "AppServerLink.h"
18466871ccSAxel Dörfler #include "PrivateScreen.h"
19466871ccSAxel Dörfler #include "ServerProtocol.h"
20466871ccSAxel Dörfler 
2157a6c095SAxel Dörfler #include <Application.h>
22a817d6adSAxel Dörfler #include <Autolock.h>
2316046321SStefano Ceccherini #include <Bitmap.h>
248eae8b05SStefano Ceccherini #include <Locker.h>
25b66d7537SAxel Dörfler #include <ObjectList.h>
26624df6c6SStefano Ceccherini #include <Window.h>
27314a1024SStefano Ceccherini 
28466871ccSAxel Dörfler #include <new>
29624df6c6SStefano Ceccherini 
30466871ccSAxel Dörfler #include <stdlib.h>
3139ffb980SStefano Ceccherini 
32624df6c6SStefano Ceccherini 
33b66d7537SAxel Dörfler static BObjectList<BPrivateScreen> sScreens(2, true);
348eae8b05SStefano Ceccherini 
358eae8b05SStefano Ceccherini // used to synchronize creation/deletion of the sScreen object
368eae8b05SStefano Ceccherini static BLocker sScreenLock("screen lock");
37624df6c6SStefano Ceccherini 
38624df6c6SStefano Ceccherini 
39ca8ed922SStefano Ceccherini using namespace BPrivate;
40ca8ed922SStefano Ceccherini 
41624df6c6SStefano Ceccherini BPrivateScreen *
42b66d7537SAxel Dörfler BPrivateScreen::Get(BWindow *window)
43624df6c6SStefano Ceccherini {
44d9525baaSAxel Dörfler 	screen_id id = B_MAIN_SCREEN_ID;
45d9525baaSAxel Dörfler 
46d9525baaSAxel Dörfler 	if (window != NULL) {
47d9525baaSAxel Dörfler 		BPrivate::AppServerLink link;
48d9525baaSAxel Dörfler 		link.StartMessage(AS_GET_SCREEN_ID_FROM_WINDOW);
49d9525baaSAxel Dörfler 		link.Attach<int32>(_get_object_token_(window));
50d9525baaSAxel Dörfler 
51d9525baaSAxel Dörfler 		status_t status;
52d9525baaSAxel Dörfler 		if (link.FlushWithReply(status) == B_OK && status == B_OK)
53d9525baaSAxel Dörfler 			link.Read<screen_id>(&id);
54d9525baaSAxel Dörfler 	}
55d9525baaSAxel Dörfler 
56b66d7537SAxel Dörfler 	return _Get(id, false);
57624df6c6SStefano Ceccherini }
58624df6c6SStefano Ceccherini 
59624df6c6SStefano Ceccherini 
60624df6c6SStefano Ceccherini BPrivateScreen *
61b66d7537SAxel Dörfler BPrivateScreen::Get(screen_id id)
62b66d7537SAxel Dörfler {
63b66d7537SAxel Dörfler 	return _Get(id, true);
64b66d7537SAxel Dörfler }
65b66d7537SAxel Dörfler 
66b66d7537SAxel Dörfler 
67b66d7537SAxel Dörfler BPrivateScreen *
68b66d7537SAxel Dörfler BPrivateScreen::_Get(screen_id id, bool check)
69624df6c6SStefano Ceccherini {
7057a6c095SAxel Dörfler 	// Nothing works without an app_server connection
7157a6c095SAxel Dörfler 	if (be_app == NULL)
7257a6c095SAxel Dörfler 		return NULL;
7357a6c095SAxel Dörfler 
74a817d6adSAxel Dörfler 	BAutolock locker(sScreenLock);
758eae8b05SStefano Ceccherini 
76b66d7537SAxel Dörfler 	// search for the screen ID
77b66d7537SAxel Dörfler 
78b66d7537SAxel Dörfler 	for (int32 i = sScreens.CountItems(); i-- > 0;) {
79b66d7537SAxel Dörfler 		BPrivateScreen* screen = sScreens.ItemAt(i);
80b66d7537SAxel Dörfler 
81b66d7537SAxel Dörfler 		if (screen->ID().id == id.id) {
82b66d7537SAxel Dörfler 			screen->_Acquire();
83b66d7537SAxel Dörfler 			return screen;
84b66d7537SAxel Dörfler 		}
858eae8b05SStefano Ceccherini 	}
868eae8b05SStefano Ceccherini 
87b66d7537SAxel Dörfler 	if (check) {
88b66d7537SAxel Dörfler 		// check if ID is valid
89b66d7537SAxel Dörfler 		if (!_IsValid(id))
90b66d7537SAxel Dörfler 			return NULL;
91b66d7537SAxel Dörfler 	}
92b66d7537SAxel Dörfler 
93b66d7537SAxel Dörfler 	// we need to allocate a new one
94b66d7537SAxel Dörfler 
95b66d7537SAxel Dörfler 	BPrivateScreen* screen = new (std::nothrow) BPrivateScreen(id);
96b66d7537SAxel Dörfler 	if (screen == NULL)
97b66d7537SAxel Dörfler 		return NULL;
98b66d7537SAxel Dörfler 
99b66d7537SAxel Dörfler 	sScreens.AddItem(screen);
100b66d7537SAxel Dörfler 	return screen;
101624df6c6SStefano Ceccherini }
102624df6c6SStefano Ceccherini 
103624df6c6SStefano Ceccherini 
104624df6c6SStefano Ceccherini void
105b66d7537SAxel Dörfler BPrivateScreen::Put(BPrivateScreen* screen)
106624df6c6SStefano Ceccherini {
107b66d7537SAxel Dörfler 	if (screen == NULL)
108b66d7537SAxel Dörfler 		return;
109b66d7537SAxel Dörfler 
110b66d7537SAxel Dörfler 	BAutolock locker(sScreenLock);
111b66d7537SAxel Dörfler 
112b66d7537SAxel Dörfler 	if (screen->_Release()) {
113b66d7537SAxel Dörfler 		if (screen->ID().id != B_MAIN_SCREEN_ID.id) {
114b66d7537SAxel Dörfler 			// we always keep the main screen object around - it will
115b66d7537SAxel Dörfler 			// never go away, even if you disconnect all monitors.
116b66d7537SAxel Dörfler 			sScreens.RemoveItem(screen);
117b66d7537SAxel Dörfler 		}
118b66d7537SAxel Dörfler 	}
119624df6c6SStefano Ceccherini }
120624df6c6SStefano Ceccherini 
121624df6c6SStefano Ceccherini 
122b66d7537SAxel Dörfler BPrivateScreen*
123b66d7537SAxel Dörfler BPrivateScreen::GetNext(BPrivateScreen* screen)
124624df6c6SStefano Ceccherini {
125b66d7537SAxel Dörfler 	BAutolock locker(sScreenLock);
126b66d7537SAxel Dörfler 
127b66d7537SAxel Dörfler 	screen_id id;
128b66d7537SAxel Dörfler 	status_t status = screen->GetNextID(id);
129b66d7537SAxel Dörfler 	if (status < B_OK)
130b66d7537SAxel Dörfler 		return NULL;
131b66d7537SAxel Dörfler 
132b66d7537SAxel Dörfler 	BPrivateScreen* nextScreen = Get(id);
133b66d7537SAxel Dörfler 	if (nextScreen == NULL)
134b66d7537SAxel Dörfler 		return NULL;
135b66d7537SAxel Dörfler 
136b66d7537SAxel Dörfler 	Put(screen);
137b66d7537SAxel Dörfler 	return nextScreen;
138624df6c6SStefano Ceccherini }
139624df6c6SStefano Ceccherini 
140624df6c6SStefano Ceccherini 
141b66d7537SAxel Dörfler bool
142b66d7537SAxel Dörfler BPrivateScreen::_IsValid(screen_id id)
143b66d7537SAxel Dörfler {
144b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
145b66d7537SAxel Dörfler 	link.StartMessage(AS_VALID_SCREEN_ID);
146b66d7537SAxel Dörfler 	link.Attach<screen_id>(id);
147b66d7537SAxel Dörfler 
148b66d7537SAxel Dörfler 	status_t status;
149b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
150b66d7537SAxel Dörfler 		return false;
151b66d7537SAxel Dörfler 
152b66d7537SAxel Dörfler 	return true;
153b66d7537SAxel Dörfler }
154b66d7537SAxel Dörfler 
155b66d7537SAxel Dörfler 
156b66d7537SAxel Dörfler //	#pragma mark -
157b66d7537SAxel Dörfler 
158b66d7537SAxel Dörfler 
159624df6c6SStefano Ceccherini color_space
160624df6c6SStefano Ceccherini BPrivateScreen::ColorSpace()
161624df6c6SStefano Ceccherini {
162624df6c6SStefano Ceccherini 	display_mode mode;
1631f41d635SStefano Ceccherini 	if (GetMode(B_CURRENT_WORKSPACE, &mode) == B_OK)
164624df6c6SStefano Ceccherini 		return (color_space)mode.space;
165624df6c6SStefano Ceccherini 
166624df6c6SStefano Ceccherini 	return B_NO_COLOR_SPACE;
167624df6c6SStefano Ceccherini }
168624df6c6SStefano Ceccherini 
169624df6c6SStefano Ceccherini 
170624df6c6SStefano Ceccherini BRect
171624df6c6SStefano Ceccherini BPrivateScreen::Frame()
172624df6c6SStefano Ceccherini {
17339ffb980SStefano Ceccherini 	// If something goes wrong, we just return this rectangle.
17439ffb980SStefano Ceccherini 
175b66d7537SAxel Dörfler 	if (system_time() > fLastUpdate + 100000) {
176b66d7537SAxel Dörfler 		// invalidate the settings after 0.1 secs
177b66d7537SAxel Dörfler 		display_mode mode;
178b66d7537SAxel Dörfler 		if (GetMode(B_CURRENT_WORKSPACE, &mode) == B_OK) {
179b66d7537SAxel Dörfler 			fFrame.Set(0, 0, (float)mode.virtual_width - 1,
180b66d7537SAxel Dörfler 				(float)mode.virtual_height - 1);
181b66d7537SAxel Dörfler 			fLastUpdate = system_time();
182b66d7537SAxel Dörfler 		}
183b66d7537SAxel Dörfler 	}
184b66d7537SAxel Dörfler 
185b66d7537SAxel Dörfler 	return fFrame;
186624df6c6SStefano Ceccherini }
187624df6c6SStefano Ceccherini 
188624df6c6SStefano Ceccherini 
189b66d7537SAxel Dörfler bool
190b66d7537SAxel Dörfler BPrivateScreen::IsValid() const
191624df6c6SStefano Ceccherini {
192b66d7537SAxel Dörfler 	return BPrivateScreen::_IsValid(ID());
193b66d7537SAxel Dörfler }
194b66d7537SAxel Dörfler 
195b66d7537SAxel Dörfler 
196b66d7537SAxel Dörfler status_t
197b66d7537SAxel Dörfler BPrivateScreen::GetNextID(screen_id& id)
198b66d7537SAxel Dörfler {
199b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
200b66d7537SAxel Dörfler 	link.StartMessage(AS_GET_NEXT_SCREEN_ID);
201b66d7537SAxel Dörfler 	link.Attach<screen_id>(ID());
202b66d7537SAxel Dörfler 
203b66d7537SAxel Dörfler 	status_t status;
204b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
205b66d7537SAxel Dörfler 		link.Read<screen_id>(&id);
206b66d7537SAxel Dörfler 		return B_OK;
207b66d7537SAxel Dörfler 	}
208b66d7537SAxel Dörfler 
209b66d7537SAxel Dörfler 	return status;
210624df6c6SStefano Ceccherini }
211624df6c6SStefano Ceccherini 
212624df6c6SStefano Ceccherini 
213624df6c6SStefano Ceccherini status_t
214624df6c6SStefano Ceccherini BPrivateScreen::WaitForRetrace(bigtime_t timeout)
215624df6c6SStefano Ceccherini {
216*5ec797a7SStephan Aßmus // TODO: remove when interrupts are enabled again in the ATI driver
217*5ec797a7SStephan Aßmus return B_ERROR;
218624df6c6SStefano Ceccherini 	// Get the retrace semaphore if it's the first time
219624df6c6SStefano Ceccherini 	// we are called. Cache the value then.
220*5ec797a7SStephan Aßmus 	if (!fRetraceSemValid)
221a817d6adSAxel Dörfler 		fRetraceSem = _RetraceSemaphore();
222624df6c6SStefano Ceccherini 
223*5ec797a7SStephan Aßmus 	if (fRetraceSem < 0) {
224*5ec797a7SStephan Aßmus 		// syncing to retrace is not supported by the accelerant
225*5ec797a7SStephan Aßmus 		return fRetraceSem;
226*5ec797a7SStephan Aßmus 	}
227*5ec797a7SStephan Aßmus 
228*5ec797a7SStephan Aßmus 	status_t status;
229624df6c6SStefano Ceccherini 	do {
230624df6c6SStefano Ceccherini 		status = acquire_sem_etc(fRetraceSem, 1, B_RELATIVE_TIMEOUT, timeout);
231624df6c6SStefano Ceccherini 	} while (status == B_INTERRUPTED);
232624df6c6SStefano Ceccherini 
233624df6c6SStefano Ceccherini 	return status;
234624df6c6SStefano Ceccherini }
235624df6c6SStefano Ceccherini 
236624df6c6SStefano Ceccherini 
237624df6c6SStefano Ceccherini uint8
238624df6c6SStefano Ceccherini BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
239624df6c6SStefano Ceccherini {
240624df6c6SStefano Ceccherini 	// Looks like this check is necessary
241a817d6adSAxel Dörfler 	if (red == B_TRANSPARENT_COLOR.red
242a817d6adSAxel Dörfler 		&& green == B_TRANSPARENT_COLOR.green
243a817d6adSAxel Dörfler 		&& blue == B_TRANSPARENT_COLOR.blue
244a817d6adSAxel Dörfler 		&& alpha == B_TRANSPARENT_COLOR.alpha)
245624df6c6SStefano Ceccherini 		return B_TRANSPARENT_8_BIT;
246624df6c6SStefano Ceccherini 
2470ef40c5eSMichael Lotz 	uint16 index = ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | (blue >> 3);
248a817d6adSAxel Dörfler 	if (ColorMap())
2492ed35bc8SStefano Ceccherini 		return fColorMap->index_map[index];
250624df6c6SStefano Ceccherini 
251624df6c6SStefano Ceccherini 	return 0;
252624df6c6SStefano Ceccherini }
253624df6c6SStefano Ceccherini 
254624df6c6SStefano Ceccherini 
255624df6c6SStefano Ceccherini rgb_color
256624df6c6SStefano Ceccherini BPrivateScreen::ColorForIndex(const uint8 index)
257624df6c6SStefano Ceccherini {
258a817d6adSAxel Dörfler 	if (ColorMap())
259624df6c6SStefano Ceccherini 		return fColorMap->color_list[index];
260624df6c6SStefano Ceccherini 
261624df6c6SStefano Ceccherini 	return rgb_color();
262624df6c6SStefano Ceccherini }
263624df6c6SStefano Ceccherini 
264624df6c6SStefano Ceccherini 
265624df6c6SStefano Ceccherini uint8
266624df6c6SStefano Ceccherini BPrivateScreen::InvertIndex(uint8 index)
267624df6c6SStefano Ceccherini {
268a817d6adSAxel Dörfler 	if (ColorMap())
269624df6c6SStefano Ceccherini 		return fColorMap->inversion_map[index];
270624df6c6SStefano Ceccherini 
271624df6c6SStefano Ceccherini 	return 0;
272624df6c6SStefano Ceccherini }
273624df6c6SStefano Ceccherini 
274624df6c6SStefano Ceccherini 
275624df6c6SStefano Ceccherini const color_map *
276624df6c6SStefano Ceccherini BPrivateScreen::ColorMap()
277624df6c6SStefano Ceccherini {
278a817d6adSAxel Dörfler 	if (fColorMap == NULL) {
279a817d6adSAxel Dörfler 		BAutolock locker(sScreenLock);
280a817d6adSAxel Dörfler 
281a817d6adSAxel Dörfler 		if (fColorMap != NULL) {
282a817d6adSAxel Dörfler 			// someone could have been faster than us
283a817d6adSAxel Dörfler 			return fColorMap;
284a817d6adSAxel Dörfler 		}
285a817d6adSAxel Dörfler 
286a817d6adSAxel Dörfler 		// TODO: BeOS R5 here gets the colormap pointer
287a817d6adSAxel Dörfler 		// (with BApplication::ro_offset_to_ptr() ?)
288a817d6adSAxel Dörfler 		// which is contained in a shared area created by the server.
289a817d6adSAxel Dörfler 		BPrivate::AppServerLink link;
290a817d6adSAxel Dörfler 		link.StartMessage(AS_SCREEN_GET_COLORMAP);
291a817d6adSAxel Dörfler 		link.Attach<screen_id>(ID());
292a817d6adSAxel Dörfler 
293a817d6adSAxel Dörfler 		status_t status;
294a817d6adSAxel Dörfler 		if (link.FlushWithReply(status) == B_OK && status == B_OK) {
295a817d6adSAxel Dörfler 			fColorMap = (color_map *)malloc(sizeof(color_map));
296a817d6adSAxel Dörfler 			fOwnsColorMap = true;
297a817d6adSAxel Dörfler 			link.Read<color_map>(fColorMap);
298a817d6adSAxel Dörfler 		}
299a817d6adSAxel Dörfler 	}
300a817d6adSAxel Dörfler 
301624df6c6SStefano Ceccherini 	return fColorMap;
302624df6c6SStefano Ceccherini }
303624df6c6SStefano Ceccherini 
304624df6c6SStefano Ceccherini 
305624df6c6SStefano Ceccherini status_t
306466871ccSAxel Dörfler BPrivateScreen::GetBitmap(BBitmap **_bitmap, bool drawCursor, BRect *bounds)
307624df6c6SStefano Ceccherini {
308466871ccSAxel Dörfler 	if (_bitmap == NULL)
30916046321SStefano Ceccherini 		return B_BAD_VALUE;
31016046321SStefano Ceccherini 
311a817d6adSAxel Dörfler 	BRect rect;
312a817d6adSAxel Dörfler 	if (bounds != NULL)
313a817d6adSAxel Dörfler 		rect = *bounds;
314a817d6adSAxel Dörfler 	else
315a817d6adSAxel Dörfler 		rect = Frame();
316a817d6adSAxel Dörfler 
317a817d6adSAxel Dörfler 	BBitmap* bitmap = new (std::nothrow) BBitmap(rect, ColorSpace());
318466871ccSAxel Dörfler 	if (bitmap == NULL)
319466871ccSAxel Dörfler 		return B_NO_MEMORY;
320466871ccSAxel Dörfler 
321466871ccSAxel Dörfler 	status_t status = bitmap->InitCheck();
322466871ccSAxel Dörfler 	if (status == B_OK)
323a817d6adSAxel Dörfler 		status = ReadBitmap(bitmap, drawCursor, &rect);
324466871ccSAxel Dörfler 	if (status != B_OK) {
325466871ccSAxel Dörfler 		delete bitmap;
326466871ccSAxel Dörfler 		return status;
327466871ccSAxel Dörfler 	}
328466871ccSAxel Dörfler 
329466871ccSAxel Dörfler 	*_bitmap = bitmap;
330466871ccSAxel Dörfler 	return B_OK;
331624df6c6SStefano Ceccherini }
332624df6c6SStefano Ceccherini 
333624df6c6SStefano Ceccherini 
334624df6c6SStefano Ceccherini status_t
335a817d6adSAxel Dörfler BPrivateScreen::ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bounds)
336624df6c6SStefano Ceccherini {
33716046321SStefano Ceccherini 	if (bitmap == NULL)
33816046321SStefano Ceccherini 		return B_BAD_VALUE;
33916046321SStefano Ceccherini 
34016046321SStefano Ceccherini 	BRect rect;
341a817d6adSAxel Dörfler 	if (bounds != NULL)
342a817d6adSAxel Dörfler 		rect = *bounds;
34316046321SStefano Ceccherini 	else
34416046321SStefano Ceccherini 		rect = Frame();
34516046321SStefano Ceccherini 
34616046321SStefano Ceccherini 	BPrivate::AppServerLink link;
34716046321SStefano Ceccherini 	link.StartMessage(AS_READ_BITMAP);
3489a44fdc9SAxel Dörfler 	link.Attach<int32>(bitmap->_ServerToken());
34916046321SStefano Ceccherini 	link.Attach<bool>(drawCursor);
35016046321SStefano Ceccherini 	link.Attach<BRect>(rect);
35116046321SStefano Ceccherini 
352a817d6adSAxel Dörfler 	status_t status = B_ERROR;
353a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) < B_OK || status != B_OK)
354a817d6adSAxel Dörfler 		return status;
35516046321SStefano Ceccherini 
35616046321SStefano Ceccherini 	return B_OK;
357624df6c6SStefano Ceccherini }
358624df6c6SStefano Ceccherini 
359624df6c6SStefano Ceccherini 
360624df6c6SStefano Ceccherini rgb_color
36139ffb980SStefano Ceccherini BPrivateScreen::DesktopColor(uint32 workspace)
362624df6c6SStefano Ceccherini {
3633ba7d6f3SAxel Dörfler 	rgb_color color = { 51, 102, 152, 255 };
364dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
3653ba7d6f3SAxel Dörfler 
3663ba7d6f3SAxel Dörfler 	link.StartMessage(AS_GET_DESKTOP_COLOR);
3673f319b33SMichael Lotz 	link.Attach<uint32>(workspace);
3683ba7d6f3SAxel Dörfler 
3693ba7d6f3SAxel Dörfler 	int32 code;
370dd10337fSAxel Dörfler 	if (link.FlushWithReply(code) == B_OK
371a817d6adSAxel Dörfler 		&& code == B_OK)
3723ba7d6f3SAxel Dörfler 		link.Read<rgb_color>(&color);
3733ba7d6f3SAxel Dörfler 
37439ffb980SStefano Ceccherini 	return color;
375624df6c6SStefano Ceccherini }
376624df6c6SStefano Ceccherini 
377624df6c6SStefano Ceccherini 
378624df6c6SStefano Ceccherini void
379a817d6adSAxel Dörfler BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace,
380a817d6adSAxel Dörfler 	bool makeDefault)
381624df6c6SStefano Ceccherini {
382dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
3833ba7d6f3SAxel Dörfler 
3843ba7d6f3SAxel Dörfler 	link.StartMessage(AS_SET_DESKTOP_COLOR);
38539ffb980SStefano Ceccherini 	link.Attach<rgb_color>(color);
3868f9ab4d1SAxel Dörfler 	link.Attach<uint32>(workspace);
38739ffb980SStefano Ceccherini 	link.Attach<bool>(makeDefault);
38839ffb980SStefano Ceccherini 	link.Flush();
389624df6c6SStefano Ceccherini }
390624df6c6SStefano Ceccherini 
391624df6c6SStefano Ceccherini 
392624df6c6SStefano Ceccherini status_t
393c6418981SStefano Ceccherini BPrivateScreen::ProposeMode(display_mode *target,
394c6418981SStefano Ceccherini 	const display_mode *low, const display_mode *high)
395624df6c6SStefano Ceccherini {
396c6418981SStefano Ceccherini 	// We can't return B_BAD_VALUE here, because it's used to indicate
397c6418981SStefano Ceccherini 	// that the mode returned is supported, but it doesn't fall
398c6418981SStefano Ceccherini 	// within the limit (see ProposeMode() documentation)
399c6418981SStefano Ceccherini 	if (target == NULL || low == NULL || high == NULL)
400624df6c6SStefano Ceccherini 		return B_ERROR;
401c6418981SStefano Ceccherini 
402c6418981SStefano Ceccherini 	BPrivate::AppServerLink link;
403c6418981SStefano Ceccherini 	link.StartMessage(AS_PROPOSE_MODE);
404c6418981SStefano Ceccherini 	link.Attach<screen_id>(ID());
405583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*target);
406583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*low);
407583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*high);
408583f6c3eSStefano Ceccherini 
409c6418981SStefano Ceccherini 	status_t status = B_ERROR;
410a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
411c6418981SStefano Ceccherini 		link.Read<display_mode>(target);
412a817d6adSAxel Dörfler 
413a817d6adSAxel Dörfler 		bool withinLimits;
414a817d6adSAxel Dörfler 		link.Read<bool>(&withinLimits);
415a817d6adSAxel Dörfler 		if (!withinLimits)
416a817d6adSAxel Dörfler 			status = B_BAD_VALUE;
417c6418981SStefano Ceccherini 	}
418c6418981SStefano Ceccherini 
419c6418981SStefano Ceccherini 	return status;
420624df6c6SStefano Ceccherini }
421624df6c6SStefano Ceccherini 
422624df6c6SStefano Ceccherini 
423624df6c6SStefano Ceccherini status_t
424a817d6adSAxel Dörfler BPrivateScreen::GetModeList(display_mode **_modeList, uint32 *_count)
425624df6c6SStefano Ceccherini {
426a817d6adSAxel Dörfler 	if (_modeList == NULL || _count == NULL)
42710c5dab8SStefano Ceccherini 		return B_BAD_VALUE;
42810c5dab8SStefano Ceccherini 
42910c5dab8SStefano Ceccherini 	BPrivate::AppServerLink link;
43010c5dab8SStefano Ceccherini 	link.StartMessage(AS_GET_MODE_LIST);
43110c5dab8SStefano Ceccherini 	link.Attach<screen_id>(ID());
432a817d6adSAxel Dörfler 
433a817d6adSAxel Dörfler 	status_t status = B_ERROR;
434a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
43506740743SAxel Dörfler 		uint32 count;
43606740743SAxel Dörfler 		if (link.Read<uint32>(&count) < B_OK)
43706740743SAxel Dörfler 			return B_ERROR;
43806740743SAxel Dörfler 
439a817d6adSAxel Dörfler 		// TODO: this could get too big for the link
44006740743SAxel Dörfler 		int32 size = count * sizeof(display_mode);
44106740743SAxel Dörfler 		display_mode* modeList = (display_mode *)malloc(size);
44206740743SAxel Dörfler 		if (modeList == NULL)
443a817d6adSAxel Dörfler 			return B_NO_MEMORY;
444a817d6adSAxel Dörfler 
44506740743SAxel Dörfler 		if (link.Read(modeList, size) < B_OK) {
44606740743SAxel Dörfler 			free(modeList);
44706740743SAxel Dörfler 			return B_ERROR;
44806740743SAxel Dörfler 		}
44906740743SAxel Dörfler 
45006740743SAxel Dörfler 		*_modeList = modeList;
45106740743SAxel Dörfler 		*_count = count;
45210c5dab8SStefano Ceccherini 	}
45310c5dab8SStefano Ceccherini 
45410c5dab8SStefano Ceccherini 	return status;
455624df6c6SStefano Ceccherini }
456624df6c6SStefano Ceccherini 
457624df6c6SStefano Ceccherini 
458624df6c6SStefano Ceccherini status_t
459624df6c6SStefano Ceccherini BPrivateScreen::GetMode(uint32 workspace, display_mode *mode)
460624df6c6SStefano Ceccherini {
461314a1024SStefano Ceccherini 	if (mode == NULL)
462314a1024SStefano Ceccherini 		return B_BAD_VALUE;
463314a1024SStefano Ceccherini 
464dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
46534c39bf0SStefano Ceccherini 	link.StartMessage(AS_SCREEN_GET_MODE);
46634c39bf0SStefano Ceccherini 	link.Attach<screen_id>(ID());
46739ffb980SStefano Ceccherini 	link.Attach<uint32>(workspace);
468fca6492fSStefano Ceccherini 
46934c39bf0SStefano Ceccherini 	status_t status = B_ERROR;
470a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) != B_OK
471a817d6adSAxel Dörfler 		|| status != B_OK)
47239ffb980SStefano Ceccherini 		return status;
473a817d6adSAxel Dörfler 
474a817d6adSAxel Dörfler 	link.Read<display_mode>(mode);
475a817d6adSAxel Dörfler 	return B_OK;
476624df6c6SStefano Ceccherini }
477624df6c6SStefano Ceccherini 
478624df6c6SStefano Ceccherini 
479624df6c6SStefano Ceccherini status_t
480624df6c6SStefano Ceccherini BPrivateScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
481624df6c6SStefano Ceccherini {
482314a1024SStefano Ceccherini 	if (mode == NULL)
483314a1024SStefano Ceccherini 		return B_BAD_VALUE;
484314a1024SStefano Ceccherini 
485dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
486314a1024SStefano Ceccherini 	link.StartMessage(AS_SCREEN_SET_MODE);
487314a1024SStefano Ceccherini 	link.Attach<screen_id>(ID());
48839ffb980SStefano Ceccherini 	link.Attach<uint32>(workspace);
48939ffb980SStefano Ceccherini 	link.Attach<display_mode>(*mode);
49039ffb980SStefano Ceccherini 	link.Attach<bool>(makeDefault);
491314a1024SStefano Ceccherini 
492314a1024SStefano Ceccherini 	status_t status = B_ERROR;
493a817d6adSAxel Dörfler 	link.FlushWithReply(status);
494314a1024SStefano Ceccherini 
49539ffb980SStefano Ceccherini 	return status;
496624df6c6SStefano Ceccherini }
497624df6c6SStefano Ceccherini 
498624df6c6SStefano Ceccherini 
499624df6c6SStefano Ceccherini status_t
500624df6c6SStefano Ceccherini BPrivateScreen::GetDeviceInfo(accelerant_device_info *info)
501624df6c6SStefano Ceccherini {
502c6418981SStefano Ceccherini 	if (info == NULL)
503c6418981SStefano Ceccherini 		return B_BAD_VALUE;
504c6418981SStefano Ceccherini 
505c6418981SStefano Ceccherini 	BPrivate::AppServerLink link;
506c6418981SStefano Ceccherini 	link.StartMessage(AS_GET_ACCELERANT_INFO);
507c6418981SStefano Ceccherini 	link.Attach<screen_id>(ID());
508a817d6adSAxel Dörfler 
509a817d6adSAxel Dörfler 	status_t status = B_ERROR;
510a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
511c6418981SStefano Ceccherini 		link.Read<accelerant_device_info>(info);
512c6418981SStefano Ceccherini 		return B_OK;
513c6418981SStefano Ceccherini 	}
514c6418981SStefano Ceccherini 
515a817d6adSAxel Dörfler 	return status;
516624df6c6SStefano Ceccherini }
517624df6c6SStefano Ceccherini 
518624df6c6SStefano Ceccherini 
519624df6c6SStefano Ceccherini status_t
520624df6c6SStefano Ceccherini BPrivateScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
521624df6c6SStefano Ceccherini {
52275de27f8SStefano Ceccherini 	if (mode == NULL || low == NULL || high == NULL)
52375de27f8SStefano Ceccherini 		return B_BAD_VALUE;
52475de27f8SStefano Ceccherini 
52575de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
52675de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_PIXEL_CLOCK_LIMITS);
52775de27f8SStefano Ceccherini 	link.Attach<screen_id>(ID());
52875de27f8SStefano Ceccherini 	link.Attach<display_mode>(*mode);
52975de27f8SStefano Ceccherini 
530a817d6adSAxel Dörfler 	status_t status;
531a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
53275de27f8SStefano Ceccherini 		link.Read<uint32>(low);
53375de27f8SStefano Ceccherini 		link.Read<uint32>(high);
53475de27f8SStefano Ceccherini 		return B_OK;
53575de27f8SStefano Ceccherini 	}
53675de27f8SStefano Ceccherini 
537a817d6adSAxel Dörfler 	return status;
538624df6c6SStefano Ceccherini }
539624df6c6SStefano Ceccherini 
540624df6c6SStefano Ceccherini 
541624df6c6SStefano Ceccherini status_t
542a817d6adSAxel Dörfler BPrivateScreen::GetTimingConstraints(display_timing_constraints *constraints)
543624df6c6SStefano Ceccherini {
544a817d6adSAxel Dörfler 	if (constraints == NULL)
54555b222b0SStefano Ceccherini 		return B_BAD_VALUE;
54655b222b0SStefano Ceccherini 
54775de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
54875de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_TIMING_CONSTRAINTS);
54975de27f8SStefano Ceccherini 	link.Attach<screen_id>(ID());
55075de27f8SStefano Ceccherini 
551a817d6adSAxel Dörfler 	status_t status = B_ERROR;
552a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
553a817d6adSAxel Dörfler 		link.Read<display_timing_constraints>(constraints);
55475de27f8SStefano Ceccherini 		return B_OK;
55575de27f8SStefano Ceccherini 	}
55675de27f8SStefano Ceccherini 
557a817d6adSAxel Dörfler 	return status;
558624df6c6SStefano Ceccherini }
559624df6c6SStefano Ceccherini 
560624df6c6SStefano Ceccherini 
561624df6c6SStefano Ceccherini status_t
562624df6c6SStefano Ceccherini BPrivateScreen::SetDPMS(uint32 dpmsState)
563624df6c6SStefano Ceccherini {
564dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
56555b222b0SStefano Ceccherini 	link.StartMessage(AS_SET_DPMS);
56639ffb980SStefano Ceccherini 	link.Attach<screen_id>(ID());
56739ffb980SStefano Ceccherini 	link.Attach<uint32>(dpmsState);
56855b222b0SStefano Ceccherini 
569a817d6adSAxel Dörfler 	status_t status = B_ERROR;
570a817d6adSAxel Dörfler 	link.FlushWithReply(status);
571a817d6adSAxel Dörfler 
572a817d6adSAxel Dörfler 	return status;
573624df6c6SStefano Ceccherini }
574624df6c6SStefano Ceccherini 
575624df6c6SStefano Ceccherini 
576624df6c6SStefano Ceccherini uint32
577624df6c6SStefano Ceccherini BPrivateScreen::DPMSState()
578624df6c6SStefano Ceccherini {
57939ffb980SStefano Ceccherini 	uint32 state = 0;
58055b222b0SStefano Ceccherini 
581dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
58255b222b0SStefano Ceccherini 	link.StartMessage(AS_GET_DPMS_STATE);
58339ffb980SStefano Ceccherini 	link.Attach<screen_id>(ID());
584a817d6adSAxel Dörfler 
585a817d6adSAxel Dörfler 	status_t status;
586a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
58755b222b0SStefano Ceccherini 		link.Read<uint32>(&state);
58855b222b0SStefano Ceccherini 
58939ffb980SStefano Ceccherini 	return state;
590624df6c6SStefano Ceccherini }
591624df6c6SStefano Ceccherini 
592624df6c6SStefano Ceccherini 
593624df6c6SStefano Ceccherini uint32
594624df6c6SStefano Ceccherini BPrivateScreen::DPMSCapabilites()
595624df6c6SStefano Ceccherini {
59639ffb980SStefano Ceccherini 	uint32 capabilities = 0;
59755b222b0SStefano Ceccherini 
598dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
59955b222b0SStefano Ceccherini 	link.StartMessage(AS_GET_DPMS_CAPABILITIES);
60039ffb980SStefano Ceccherini 	link.Attach<screen_id>(ID());
601a817d6adSAxel Dörfler 
602a817d6adSAxel Dörfler 	status_t status;
603a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
60455b222b0SStefano Ceccherini 		link.Read<uint32>(&capabilities);
60555b222b0SStefano Ceccherini 
60639ffb980SStefano Ceccherini 	return capabilities;
607624df6c6SStefano Ceccherini }
608624df6c6SStefano Ceccherini 
609624df6c6SStefano Ceccherini 
610624df6c6SStefano Ceccherini void *
611624df6c6SStefano Ceccherini BPrivateScreen::BaseAddress()
612624df6c6SStefano Ceccherini {
613b66d7537SAxel Dörfler 	frame_buffer_config config;
614b66d7537SAxel Dörfler 	if (_GetFrameBufferConfig(config) != B_OK)
615624df6c6SStefano Ceccherini 		return NULL;
616b66d7537SAxel Dörfler 
617b66d7537SAxel Dörfler 	return config.frame_buffer;
618624df6c6SStefano Ceccherini }
619624df6c6SStefano Ceccherini 
620624df6c6SStefano Ceccherini 
621624df6c6SStefano Ceccherini uint32
622624df6c6SStefano Ceccherini BPrivateScreen::BytesPerRow()
623624df6c6SStefano Ceccherini {
624b66d7537SAxel Dörfler 	frame_buffer_config config;
625b66d7537SAxel Dörfler 	if (_GetFrameBufferConfig(config) != B_OK)
626624df6c6SStefano Ceccherini 		return 0;
627624df6c6SStefano Ceccherini 
628b66d7537SAxel Dörfler 	return config.bytes_per_row;
629624df6c6SStefano Ceccherini }
630624df6c6SStefano Ceccherini 
631624df6c6SStefano Ceccherini 
632a817d6adSAxel Dörfler // #pragma mark - private methods
63375de27f8SStefano Ceccherini 
634a817d6adSAxel Dörfler 
635a817d6adSAxel Dörfler sem_id
636a817d6adSAxel Dörfler BPrivateScreen::_RetraceSemaphore()
637a817d6adSAxel Dörfler {
63875de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
63975de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_RETRACE_SEMAPHORE);
64075de27f8SStefano Ceccherini 	link.Attach<screen_id>(ID());
641a817d6adSAxel Dörfler 
642a817d6adSAxel Dörfler 	sem_id id = B_BAD_SEM_ID;
643*5ec797a7SStephan Aßmus 	status_t status = B_ERROR;
644*5ec797a7SStephan Aßmus 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
645*5ec797a7SStephan Aßmus 		link.Read<sem_id>(&id);
646*5ec797a7SStephan Aßmus 		fRetraceSemValid = true;
647*5ec797a7SStephan Aßmus 	}
64875de27f8SStefano Ceccherini 
64975de27f8SStefano Ceccherini 	return id;
65075de27f8SStefano Ceccherini }
65175de27f8SStefano Ceccherini 
65275de27f8SStefano Ceccherini 
653b66d7537SAxel Dörfler status_t
654b66d7537SAxel Dörfler BPrivateScreen::_GetFrameBufferConfig(frame_buffer_config& config)
655b66d7537SAxel Dörfler {
656b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
657b66d7537SAxel Dörfler 	link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG);
658b66d7537SAxel Dörfler 	link.Attach<screen_id>(ID());
659b66d7537SAxel Dörfler 
660b66d7537SAxel Dörfler 	status_t status = B_ERROR;
661b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
662b66d7537SAxel Dörfler 		link.Read<frame_buffer_config>(&config);
663b66d7537SAxel Dörfler 		return B_OK;
664b66d7537SAxel Dörfler 	}
665b66d7537SAxel Dörfler 
666b66d7537SAxel Dörfler 	return status;
667b66d7537SAxel Dörfler }
668b66d7537SAxel Dörfler 
669b66d7537SAxel Dörfler 
670b66d7537SAxel Dörfler BPrivateScreen::BPrivateScreen(screen_id id)
671624df6c6SStefano Ceccherini 	:
672b66d7537SAxel Dörfler 	fID(id),
673624df6c6SStefano Ceccherini 	fColorMap(NULL),
674624df6c6SStefano Ceccherini 	fRetraceSem(-1),
675*5ec797a7SStephan Aßmus 	fRetraceSemValid(false),
676b66d7537SAxel Dörfler 	fOwnsColorMap(false),
677b66d7537SAxel Dörfler 	fFrame(0, 0, 0, 0),
678b66d7537SAxel Dörfler 	fLastUpdate(0)
679624df6c6SStefano Ceccherini {
680624df6c6SStefano Ceccherini }
681624df6c6SStefano Ceccherini 
682624df6c6SStefano Ceccherini 
683624df6c6SStefano Ceccherini BPrivateScreen::~BPrivateScreen()
684624df6c6SStefano Ceccherini {
685624df6c6SStefano Ceccherini 	if (fOwnsColorMap)
686624df6c6SStefano Ceccherini 		free(fColorMap);
687624df6c6SStefano Ceccherini }
688