xref: /haiku/src/kits/game/DirectWindow.cpp (revision 764ac9e5aad7fe74f52bd757b8739b8cf6a3e6f6)
109ea3092SStefano Ceccherini /*
28575beb8SJérôme Duval  * Copyright 2003-2005, Haiku Inc.
317495d0bSStefano Ceccherini  * Authors:
409ea3092SStefano Ceccherini  *		Stefano Ceccherini (burton666@libero.it).
509ea3092SStefano Ceccherini  *		Carwyn Jones (turok2@currantbun.com)
617495d0bSStefano Ceccherini  *
709ea3092SStefano Ceccherini  * Distributed under the terms of the MIT License.
809ea3092SStefano Ceccherini  */
90b4a36abSbeveloper 
10366fdcdfSMarcus Overhagen 
11cafaa5aaSStefano Ceccherini #include <DirectWindow.h>
12cafaa5aaSStefano Ceccherini #include <clipping.h>
130b4a36abSbeveloper 
14*764ac9e5SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_BEOS
15cafaa5aaSStefano Ceccherini #	include <R5_AppServerLink.h>
16cafaa5aaSStefano Ceccherini #	include <R5_Session.h>
17feee8cf2SStefano Ceccherini #	define DW_GET_SYNC_DATA		0x880
18feee8cf2SStefano Ceccherini #	define DW_SET_FULLSCREEN		0x881
19feee8cf2SStefano Ceccherini #	define DW_SUPPORTS_WINDOW_MODE 0xF2C
20*764ac9e5SAxel Dörfler #else
21feee8cf2SStefano Ceccherini #	include <AppServerLink.h>
22feee8cf2SStefano Ceccherini #	include <ServerProtocol.h>
23feee8cf2SStefano Ceccherini #endif
24366fdcdfSMarcus Overhagen 
25*764ac9e5SAxel Dörfler // Compiling for Dano/Zeta is broken as it doesn't have BRegion::set_size()
26*764ac9e5SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_DANO
27*764ac9e5SAxel Dörfler #	warning "##### Building BDirectWindow for TARGET_PLATFORM=dano (DANO/Zeta) is broken #####"
28*764ac9e5SAxel Dörfler #endif
29*764ac9e5SAxel Dörfler 
30*764ac9e5SAxel Dörfler 
31cafaa5aaSStefano Ceccherini // TODO: We'll want to move this to a private header,
32cafaa5aaSStefano Ceccherini // accessible by the app server.
33*764ac9e5SAxel Dörfler struct dw_sync_data {
34cafaa5aaSStefano Ceccherini 	area_id area;
35cafaa5aaSStefano Ceccherini 	sem_id disableSem;
36cafaa5aaSStefano Ceccherini 	sem_id disableSemAck;
37cafaa5aaSStefano Ceccherini };
38cafaa5aaSStefano Ceccherini 
39cafaa5aaSStefano Ceccherini 
40cafaa5aaSStefano Ceccherini // We don't need this kind of locking, since the directDeamonFunc
41cafaa5aaSStefano Ceccherini // doesn't access critical shared data.
42cafaa5aaSStefano Ceccherini #define DW_NEEDS_LOCKING 0
43cafaa5aaSStefano Ceccherini 
44cafaa5aaSStefano Ceccherini enum dw_status_bits {
4517495d0bSStefano Ceccherini 	DW_STATUS_AREA_CLONED	 = 0x1,
4617495d0bSStefano Ceccherini 	DW_STATUS_THREAD_STARTED = 0x2,
4717495d0bSStefano Ceccherini 	DW_STATUS_SEM_CREATED	 = 0x4
48cafaa5aaSStefano Ceccherini };
49cafaa5aaSStefano Ceccherini 
50cafaa5aaSStefano Ceccherini 
51*764ac9e5SAxel Dörfler BDirectWindow::BDirectWindow(BRect frame, const char *title, window_type type,
52*764ac9e5SAxel Dörfler 	uint32 flags, uint32 workspace)
53cafaa5aaSStefano Ceccherini 	: BWindow(frame, title, type, flags, workspace)
54cafaa5aaSStefano Ceccherini {
55cafaa5aaSStefano Ceccherini 	InitData();
560b4a36abSbeveloper }
570b4a36abSbeveloper 
580b4a36abSbeveloper 
59*764ac9e5SAxel Dörfler BDirectWindow::BDirectWindow(BRect frame, const char *title, window_look look,
60*764ac9e5SAxel Dörfler 	window_feel feel, uint32 flags, uint32 workspace)
61cafaa5aaSStefano Ceccherini 	: BWindow(frame, title, look, feel, flags, workspace)
620b4a36abSbeveloper {
63cafaa5aaSStefano Ceccherini 	InitData();
640b4a36abSbeveloper }
650b4a36abSbeveloper 
660b4a36abSbeveloper 
670b4a36abSbeveloper BDirectWindow::~BDirectWindow()
680b4a36abSbeveloper {
69cafaa5aaSStefano Ceccherini 	DisposeData();
700b4a36abSbeveloper }
710b4a36abSbeveloper 
720b4a36abSbeveloper 
73cafaa5aaSStefano Ceccherini // start of regular BWindow API
740b4a36abSbeveloper BArchivable *
750b4a36abSbeveloper BDirectWindow::Instantiate(BMessage *data)
760b4a36abSbeveloper {
770b4a36abSbeveloper 	return NULL;
780b4a36abSbeveloper }
790b4a36abSbeveloper 
800b4a36abSbeveloper 
810b4a36abSbeveloper status_t
82cafaa5aaSStefano Ceccherini BDirectWindow::Archive(BMessage *data, bool deep) const
830b4a36abSbeveloper {
84cafaa5aaSStefano Ceccherini 	return inherited::Archive(data, deep);
850b4a36abSbeveloper }
860b4a36abSbeveloper 
870b4a36abSbeveloper 
880b4a36abSbeveloper void
89cafaa5aaSStefano Ceccherini BDirectWindow::Quit()
900b4a36abSbeveloper {
91cafaa5aaSStefano Ceccherini 	inherited::Quit();
920b4a36abSbeveloper }
930b4a36abSbeveloper 
940b4a36abSbeveloper 
950b4a36abSbeveloper void
96cafaa5aaSStefano Ceccherini BDirectWindow::DispatchMessage(BMessage *message, BHandler *handler)
970b4a36abSbeveloper {
98cafaa5aaSStefano Ceccherini 	inherited::DispatchMessage(message, handler);
990b4a36abSbeveloper }
1000b4a36abSbeveloper 
1010b4a36abSbeveloper 
1020b4a36abSbeveloper void
1030b4a36abSbeveloper BDirectWindow::MessageReceived(BMessage *message)
1040b4a36abSbeveloper {
105cafaa5aaSStefano Ceccherini 	inherited::MessageReceived(message);
1060b4a36abSbeveloper }
1070b4a36abSbeveloper 
1080b4a36abSbeveloper 
1090b4a36abSbeveloper void
1100b4a36abSbeveloper BDirectWindow::FrameMoved(BPoint new_position)
1110b4a36abSbeveloper {
112cafaa5aaSStefano Ceccherini 	inherited::FrameMoved(new_position);
1130b4a36abSbeveloper }
1140b4a36abSbeveloper 
1150b4a36abSbeveloper 
1160b4a36abSbeveloper void
117cafaa5aaSStefano Ceccherini BDirectWindow::WorkspacesChanged(uint32 old_ws, uint32 new_ws)
1180b4a36abSbeveloper {
119cafaa5aaSStefano Ceccherini 	inherited::WorkspacesChanged(old_ws, new_ws);
1200b4a36abSbeveloper }
1210b4a36abSbeveloper 
1220b4a36abSbeveloper 
1230b4a36abSbeveloper void
124cafaa5aaSStefano Ceccherini BDirectWindow::WorkspaceActivated(int32 ws, bool state)
1250b4a36abSbeveloper {
126cafaa5aaSStefano Ceccherini 	inherited::WorkspaceActivated(ws, state);
1270b4a36abSbeveloper }
1280b4a36abSbeveloper 
1290b4a36abSbeveloper 
1300b4a36abSbeveloper void
131cafaa5aaSStefano Ceccherini BDirectWindow::FrameResized(float new_width, float new_height)
1320b4a36abSbeveloper {
133cafaa5aaSStefano Ceccherini 	inherited::FrameResized(new_width, new_height);
1340b4a36abSbeveloper }
1350b4a36abSbeveloper 
1360b4a36abSbeveloper 
1370b4a36abSbeveloper void
1380b4a36abSbeveloper BDirectWindow::Minimize(bool minimize)
1390b4a36abSbeveloper {
140cafaa5aaSStefano Ceccherini 	inherited::Minimize(minimize);
1410b4a36abSbeveloper }
1420b4a36abSbeveloper 
1430b4a36abSbeveloper 
1440b4a36abSbeveloper void
145cafaa5aaSStefano Ceccherini BDirectWindow::Zoom(BPoint rec_position, float rec_width, float rec_height)
1460b4a36abSbeveloper {
147cafaa5aaSStefano Ceccherini 	inherited::Zoom(rec_position, rec_width, rec_height);
1480b4a36abSbeveloper }
1490b4a36abSbeveloper 
1500b4a36abSbeveloper 
1510b4a36abSbeveloper void
152cafaa5aaSStefano Ceccherini BDirectWindow::ScreenChanged(BRect screen_size, color_space depth)
1530b4a36abSbeveloper {
154cafaa5aaSStefano Ceccherini 	inherited::ScreenChanged(screen_size, depth);
1550b4a36abSbeveloper }
1560b4a36abSbeveloper 
1570b4a36abSbeveloper 
1580b4a36abSbeveloper void
1590b4a36abSbeveloper BDirectWindow::MenusBeginning()
1600b4a36abSbeveloper {
161cafaa5aaSStefano Ceccherini 	inherited::MenusBeginning();
1620b4a36abSbeveloper }
1630b4a36abSbeveloper 
1640b4a36abSbeveloper 
1650b4a36abSbeveloper void
1660b4a36abSbeveloper BDirectWindow::MenusEnded()
1670b4a36abSbeveloper {
168cafaa5aaSStefano Ceccherini 	inherited::MenusEnded();
1690b4a36abSbeveloper }
1700b4a36abSbeveloper 
1710b4a36abSbeveloper 
1720b4a36abSbeveloper void
1730b4a36abSbeveloper BDirectWindow::WindowActivated(bool state)
1740b4a36abSbeveloper {
175cafaa5aaSStefano Ceccherini 	inherited::WindowActivated(state);
1760b4a36abSbeveloper }
1770b4a36abSbeveloper 
1780b4a36abSbeveloper 
1790b4a36abSbeveloper void
1800b4a36abSbeveloper BDirectWindow::Show()
1810b4a36abSbeveloper {
182cafaa5aaSStefano Ceccherini 	inherited::Show();
1830b4a36abSbeveloper }
1840b4a36abSbeveloper 
1850b4a36abSbeveloper 
1860b4a36abSbeveloper void
1870b4a36abSbeveloper BDirectWindow::Hide()
1880b4a36abSbeveloper {
189cafaa5aaSStefano Ceccherini 	inherited::Hide();
1900b4a36abSbeveloper }
1910b4a36abSbeveloper 
1920b4a36abSbeveloper 
1930b4a36abSbeveloper BHandler *
194cafaa5aaSStefano Ceccherini BDirectWindow::ResolveSpecifier(BMessage *msg, int32 index,
195cafaa5aaSStefano Ceccherini 	BMessage *specifier, int32 form, const char *property)
1960b4a36abSbeveloper {
197cafaa5aaSStefano Ceccherini 	return inherited::ResolveSpecifier(msg, index, specifier, form, property);
1980b4a36abSbeveloper }
1990b4a36abSbeveloper 
2000b4a36abSbeveloper 
2010b4a36abSbeveloper status_t
2020b4a36abSbeveloper BDirectWindow::GetSupportedSuites(BMessage *data)
2030b4a36abSbeveloper {
204cafaa5aaSStefano Ceccherini 	return inherited::GetSupportedSuites(data);
2050b4a36abSbeveloper }
2060b4a36abSbeveloper 
2070b4a36abSbeveloper 
2080b4a36abSbeveloper status_t
209cafaa5aaSStefano Ceccherini BDirectWindow::Perform(perform_code d, void *arg)
2100b4a36abSbeveloper {
211cafaa5aaSStefano Ceccherini 	return inherited::Perform(d, arg);
2120b4a36abSbeveloper }
2130b4a36abSbeveloper 
2140b4a36abSbeveloper 
215b816dc1eSIngo Weinhold void
216b816dc1eSIngo Weinhold BDirectWindow::task_looper()
217b816dc1eSIngo Weinhold {
218cafaa5aaSStefano Ceccherini 	inherited::task_looper();
219b816dc1eSIngo Weinhold }
220b816dc1eSIngo Weinhold 
221cafaa5aaSStefano Ceccherini 
222b816dc1eSIngo Weinhold BMessage *
223b816dc1eSIngo Weinhold BDirectWindow::ConvertToMessage(void *raw, int32 code)
224b816dc1eSIngo Weinhold {
225cafaa5aaSStefano Ceccherini 	return inherited::ConvertToMessage(raw, code);
226b816dc1eSIngo Weinhold }
2270b4a36abSbeveloper 
2280b4a36abSbeveloper 
229*764ac9e5SAxel Dörfler //	#pragma mark - BDirectWindow specific API
230*764ac9e5SAxel Dörfler 
231*764ac9e5SAxel Dörfler 
2320b4a36abSbeveloper void
2330b4a36abSbeveloper BDirectWindow::DirectConnected(direct_buffer_info *info)
2340b4a36abSbeveloper {
235cafaa5aaSStefano Ceccherini 	// implemented in subclasses
2360b4a36abSbeveloper }
2370b4a36abSbeveloper 
2380b4a36abSbeveloper 
2390b4a36abSbeveloper status_t
240cafaa5aaSStefano Ceccherini BDirectWindow::GetClippingRegion(BRegion *region, BPoint *origin) const
2410b4a36abSbeveloper {
242cafaa5aaSStefano Ceccherini 	if (region == NULL)
243cafaa5aaSStefano Ceccherini 		return B_BAD_VALUE;
244cafaa5aaSStefano Ceccherini 
2454f6f70e0SStefano Ceccherini 	if (IsLocked() || !LockDirect())
2465fdea13fSStefano Ceccherini 		return B_ERROR;
2475fdea13fSStefano Ceccherini 
248cafaa5aaSStefano Ceccherini 	if (in_direct_connect) {
249cafaa5aaSStefano Ceccherini 		UnlockDirect();
250cafaa5aaSStefano Ceccherini 		return B_ERROR;
251cafaa5aaSStefano Ceccherini 	}
252cafaa5aaSStefano Ceccherini 
253cafaa5aaSStefano Ceccherini 	// BPoint's coordinates are floats. We can only work
254cafaa5aaSStefano Ceccherini 	// with integers.
255cafaa5aaSStefano Ceccherini 	int32 originX, originY;
256cafaa5aaSStefano Ceccherini 	if (origin == NULL) {
257cafaa5aaSStefano Ceccherini 		originX = 0;
258cafaa5aaSStefano Ceccherini 		originY = 0;
259cafaa5aaSStefano Ceccherini 	} else {
260cafaa5aaSStefano Ceccherini 		originX = (int32)origin->x;
261cafaa5aaSStefano Ceccherini 		originY = (int32)origin->y;
262cafaa5aaSStefano Ceccherini 	}
263cafaa5aaSStefano Ceccherini 
264*764ac9e5SAxel Dörfler #ifndef HAIKU_TARGET_PLATFORM_DANO
265cafaa5aaSStefano Ceccherini 	// Since we are friend of BRegion, we can access its private members.
266cafaa5aaSStefano Ceccherini 	// Otherwise, we would need to call BRegion::Include(clipping_rect)
267cafaa5aaSStefano Ceccherini 	// for every clipping_rect in our clip_list, and that would be much
2685fdea13fSStefano Ceccherini 	// more overkill than this (tested ).
269cafaa5aaSStefano Ceccherini 	region->set_size(buffer_desc->clip_list_count);
270cafaa5aaSStefano Ceccherini 	region->count = buffer_desc->clip_list_count;
271cafaa5aaSStefano Ceccherini 	region->bound = buffer_desc->clip_bounds;
2724f6f70e0SStefano Ceccherini 	for (uint32 c = 0; c < buffer_desc->clip_list_count; c++)
2734f6f70e0SStefano Ceccherini 		region->data[c] = buffer_desc->clip_list[c];
274cafaa5aaSStefano Ceccherini 
275cafaa5aaSStefano Ceccherini 	// adjust bounds by the given origin point
2764f6f70e0SStefano Ceccherini 	region->OffsetBy(-originX, -originY);
277366fdcdfSMarcus Overhagen #endif
278366fdcdfSMarcus Overhagen 
279cafaa5aaSStefano Ceccherini 	UnlockDirect();
280cafaa5aaSStefano Ceccherini 
281cafaa5aaSStefano Ceccherini 	return B_OK;
282cafaa5aaSStefano Ceccherini 
2830b4a36abSbeveloper }
2840b4a36abSbeveloper 
2850b4a36abSbeveloper 
2860b4a36abSbeveloper status_t
2870b4a36abSbeveloper BDirectWindow::SetFullScreen(bool enable)
2880b4a36abSbeveloper {
289cafaa5aaSStefano Ceccherini 	status_t status = B_ERROR;
29009ea3092SStefano Ceccherini 	if (Lock()) {
291*764ac9e5SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_BEOS
29209ea3092SStefano Ceccherini 		a_session->swrite_l(DW_SET_FULLSCREEN);
29309ea3092SStefano Ceccherini 		a_session->swrite_l(server_token);
29417495d0bSStefano Ceccherini 		a_session->swrite_l((int32)enable);
29509ea3092SStefano Ceccherini 		Flush();
29609ea3092SStefano Ceccherini 
297bfc3bb18SStefano Ceccherini 		status_t fullScreen;
298bfc3bb18SStefano Ceccherini 		a_session->sread(sizeof(status_t), &fullScreen);
299bfc3bb18SStefano Ceccherini 		a_session->sread(sizeof(status_t), &status);
300feee8cf2SStefano Ceccherini 		full_screen_enable = enable;
301*764ac9e5SAxel Dörfler #else
302feee8cf2SStefano Ceccherini 		fLink->StartMessage(AS_DW_SET_FULLSCREEN);
303feee8cf2SStefano Ceccherini 		fLink->Attach<int32>(server_token); // useless ?
304feee8cf2SStefano Ceccherini 		fLink->Attach<bool>(enable);
305feee8cf2SStefano Ceccherini 
306feee8cf2SStefano Ceccherini 		int32 code;
307feee8cf2SStefano Ceccherini 		if (fLink->FlushWithReply(code) == B_OK
308feee8cf2SStefano Ceccherini 			&& code == SERVER_TRUE) {
309feee8cf2SStefano Ceccherini 			status = B_OK;
310feee8cf2SStefano Ceccherini 			full_screen_enable = enable;
311feee8cf2SStefano Ceccherini 		}
3128575beb8SJérôme Duval #endif
31309ea3092SStefano Ceccherini 		Unlock();
314bfc3bb18SStefano Ceccherini 
31509ea3092SStefano Ceccherini 	}
316cafaa5aaSStefano Ceccherini 	return status;
3170b4a36abSbeveloper }
3180b4a36abSbeveloper 
3190b4a36abSbeveloper 
3200b4a36abSbeveloper bool
3210b4a36abSbeveloper BDirectWindow::IsFullScreen() const
3220b4a36abSbeveloper {
323cafaa5aaSStefano Ceccherini 	return full_screen_enable;
3240b4a36abSbeveloper }
3250b4a36abSbeveloper 
3260b4a36abSbeveloper 
3270b4a36abSbeveloper bool
328cafaa5aaSStefano Ceccherini BDirectWindow::SupportsWindowMode(screen_id id)
3290b4a36abSbeveloper {
330*764ac9e5SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_BEOS
331feee8cf2SStefano Ceccherini 	int32 result = 0;
332cafaa5aaSStefano Ceccherini 	_BAppServerLink_ link;
333cafaa5aaSStefano Ceccherini 	link.fSession->swrite_l(DW_SUPPORTS_WINDOW_MODE);
334cafaa5aaSStefano Ceccherini 	link.fSession->swrite_l(id.id);
335cafaa5aaSStefano Ceccherini 	link.fSession->sync();
336cafaa5aaSStefano Ceccherini 	link.fSession->sread(sizeof(result), &result);
337feee8cf2SStefano Ceccherini 	return result & true;
338*764ac9e5SAxel Dörfler #else
339feee8cf2SStefano Ceccherini 	BPrivate::AppServerLink link;
340feee8cf2SStefano Ceccherini 	link.StartMessage(AS_DW_SUPPORTS_WINDOW_MODE);
341feee8cf2SStefano Ceccherini 	link.Attach<screen_id>(id);
342feee8cf2SStefano Ceccherini 	int32 reply;
343feee8cf2SStefano Ceccherini 	if (link.FlushWithReply(reply) == B_OK
344feee8cf2SStefano Ceccherini 		&& reply == SERVER_TRUE)
345feee8cf2SStefano Ceccherini 		return true;
346feee8cf2SStefano Ceccherini #endif
347feee8cf2SStefano Ceccherini 
348feee8cf2SStefano Ceccherini 	return false;
349cafaa5aaSStefano Ceccherini }
350cafaa5aaSStefano Ceccherini 
351cafaa5aaSStefano Ceccherini 
352cafaa5aaSStefano Ceccherini // Private methods
353cafaa5aaSStefano Ceccherini int32
354cafaa5aaSStefano Ceccherini BDirectWindow::DirectDeamonFunc(void *arg)
355cafaa5aaSStefano Ceccherini {
356cafaa5aaSStefano Ceccherini 	BDirectWindow *object = static_cast<BDirectWindow *>(arg);
357cafaa5aaSStefano Ceccherini 
358cafaa5aaSStefano Ceccherini 	while (!object->deamon_killer) {
359cafaa5aaSStefano Ceccherini 		// This sem is released by the app_server when our
360cafaa5aaSStefano Ceccherini 		// clipping region changes, or when our window is moved,
361cafaa5aaSStefano Ceccherini 		// resized, etc. etc.
362cafaa5aaSStefano Ceccherini 		while (acquire_sem(object->disable_sem) == B_INTERRUPTED)
363cafaa5aaSStefano Ceccherini 			;
364cafaa5aaSStefano Ceccherini 
365cafaa5aaSStefano Ceccherini 		if (object->LockDirect()) {
366cafaa5aaSStefano Ceccherini 			if ((object->buffer_desc->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_START)
367cafaa5aaSStefano Ceccherini 				object->connection_enable = true;
368cafaa5aaSStefano Ceccherini 
369cafaa5aaSStefano Ceccherini 			object->in_direct_connect = true;
370cafaa5aaSStefano Ceccherini 			object->DirectConnected(object->buffer_desc);
371cafaa5aaSStefano Ceccherini 			object->in_direct_connect = false;
372cafaa5aaSStefano Ceccherini 
373cafaa5aaSStefano Ceccherini 			if ((object->buffer_desc->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP)
374cafaa5aaSStefano Ceccherini 				object->connection_enable = false;
375cafaa5aaSStefano Ceccherini 
376cafaa5aaSStefano Ceccherini 			object->UnlockDirect();
377cafaa5aaSStefano Ceccherini 		}
378cafaa5aaSStefano Ceccherini 
379cafaa5aaSStefano Ceccherini 		// The app_server then waits (with a timeout) on this sem.
380cafaa5aaSStefano Ceccherini 		// If we aren't quick enough to release this sem, our app
381cafaa5aaSStefano Ceccherini 		// will be terminated by the app_server
382cafaa5aaSStefano Ceccherini 		release_sem(object->disable_sem_ack);
383cafaa5aaSStefano Ceccherini 	}
384cafaa5aaSStefano Ceccherini 
385cafaa5aaSStefano Ceccherini 	return 0;
386cafaa5aaSStefano Ceccherini }
387cafaa5aaSStefano Ceccherini 
388cafaa5aaSStefano Ceccherini 
38917495d0bSStefano Ceccherini // LockDirect() and UnlockDirect() are no-op on R5. I tried to call (R5's) LockDirect()
39017495d0bSStefano Ceccherini // repeatedly, from the same thread and from different threads, nothing happened.
39117495d0bSStefano Ceccherini // I implemented them anyway, as they were the first methods I wrote
39217495d0bSStefano Ceccherini // in this class (As you can see, I even needed to cast away their constness
39317495d0bSStefano Ceccherini // to make them do something useful).
39417495d0bSStefano Ceccherini // They're not needed though, as the direct_deamon_thread doesn't change
39517495d0bSStefano Ceccherini // any shared data. They are probably here for future enhancements (see also the
39617495d0bSStefano Ceccherini // comment in DriverSetup()
397cafaa5aaSStefano Ceccherini bool
398cafaa5aaSStefano Ceccherini BDirectWindow::LockDirect() const
399cafaa5aaSStefano Ceccherini {
400cafaa5aaSStefano Ceccherini 	status_t status = B_OK;
401cafaa5aaSStefano Ceccherini 
402cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
403cafaa5aaSStefano Ceccherini 	BDirectWindow *casted = const_cast<BDirectWindow *>(this);
404cafaa5aaSStefano Ceccherini 
4055fdea13fSStefano Ceccherini 	if (atomic_add(&casted->direct_lock, 1) > 0) {
406cafaa5aaSStefano Ceccherini 		do {
407cafaa5aaSStefano Ceccherini 			status = acquire_sem(direct_sem);
408cafaa5aaSStefano Ceccherini 		} while (status == B_INTERRUPTED);
4095fdea13fSStefano Ceccherini 	}
410cafaa5aaSStefano Ceccherini 
411cafaa5aaSStefano Ceccherini 	if (status == B_OK) {
412cafaa5aaSStefano Ceccherini 		casted->direct_lock_owner = find_thread(NULL);
413cafaa5aaSStefano Ceccherini 		casted->direct_lock_count++;
414cafaa5aaSStefano Ceccherini 	}
415cafaa5aaSStefano Ceccherini #endif
416cafaa5aaSStefano Ceccherini 
417cafaa5aaSStefano Ceccherini 	return status == B_OK;
4180b4a36abSbeveloper }
4190b4a36abSbeveloper 
4200b4a36abSbeveloper 
4210b4a36abSbeveloper void
422cafaa5aaSStefano Ceccherini BDirectWindow::UnlockDirect() const
4230b4a36abSbeveloper {
424cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
425cafaa5aaSStefano Ceccherini 	BDirectWindow *casted = const_cast<BDirectWindow *>(this);
426cafaa5aaSStefano Ceccherini 
427cafaa5aaSStefano Ceccherini 	if (atomic_add(&casted->direct_lock, -1) > 1)
428cafaa5aaSStefano Ceccherini 		release_sem(direct_sem);
429cafaa5aaSStefano Ceccherini 
430cafaa5aaSStefano Ceccherini 	casted->direct_lock_count--;
431cafaa5aaSStefano Ceccherini #endif
4320b4a36abSbeveloper }
4330b4a36abSbeveloper 
4340b4a36abSbeveloper 
4350b4a36abSbeveloper void
436cafaa5aaSStefano Ceccherini BDirectWindow::InitData()
4370b4a36abSbeveloper {
438cafaa5aaSStefano Ceccherini 	connection_enable = false;
439cafaa5aaSStefano Ceccherini 	full_screen_enable = false;
440cafaa5aaSStefano Ceccherini 	in_direct_connect = false;
441cafaa5aaSStefano Ceccherini 
442cafaa5aaSStefano Ceccherini 	dw_init_status = 0;
443cafaa5aaSStefano Ceccherini 
444cafaa5aaSStefano Ceccherini 	direct_driver_ready = false;
445cafaa5aaSStefano Ceccherini 	direct_driver_type = 0;
446cafaa5aaSStefano Ceccherini 	direct_driver_token = 0;
447cafaa5aaSStefano Ceccherini 	direct_driver = NULL;
448cafaa5aaSStefano Ceccherini 
4495fdea13fSStefano Ceccherini 	if (!Lock())
4505fdea13fSStefano Ceccherini 		return;
4515fdea13fSStefano Ceccherini 
4528575beb8SJérôme Duval 	struct dw_sync_data sync_data;
4538575beb8SJérôme Duval 	status_t status = B_ERROR;
4548575beb8SJérôme Duval 
455*764ac9e5SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_BEOS
456cafaa5aaSStefano Ceccherini 	a_session->swrite_l(DW_GET_SYNC_DATA);
457cafaa5aaSStefano Ceccherini 	a_session->swrite_l(server_token);
4588575beb8SJérôme Duval 
459cafaa5aaSStefano Ceccherini 	Flush();
460cafaa5aaSStefano Ceccherini 
461cafaa5aaSStefano Ceccherini 	a_session->sread(sizeof(sync_data), &sync_data);
4628575beb8SJérôme Duval 	a_session->sread(sizeof(status), &status);
463*764ac9e5SAxel Dörfler #else
464feee8cf2SStefano Ceccherini 	fLink->StartMessage(AS_DW_GET_SYNC_DATA);
465feee8cf2SStefano Ceccherini 	fLink->Attach<int32>(server_token);
466feee8cf2SStefano Ceccherini 
467feee8cf2SStefano Ceccherini 	int32 reply;
468feee8cf2SStefano Ceccherini 	if (fLink->FlushWithReply(reply) == B_OK
469*764ac9e5SAxel Dörfler 		&& reply == B_OK) {
470feee8cf2SStefano Ceccherini 		fLink->Read<dw_sync_data>(&sync_data);
471feee8cf2SStefano Ceccherini 		status = B_OK;
472feee8cf2SStefano Ceccherini 	}
473feee8cf2SStefano Ceccherini #endif
474feee8cf2SStefano Ceccherini 
475cafaa5aaSStefano Ceccherini 	Unlock();
476cafaa5aaSStefano Ceccherini 
4775fdea13fSStefano Ceccherini 	if (status < B_OK)
4785fdea13fSStefano Ceccherini 		return;
479cafaa5aaSStefano Ceccherini 
480cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
481cafaa5aaSStefano Ceccherini 	direct_lock = 0;
482cafaa5aaSStefano Ceccherini 	direct_lock_count = 0;
4835fdea13fSStefano Ceccherini 	direct_lock_owner = -1;
484cafaa5aaSStefano Ceccherini 	direct_lock_stack = NULL;
485cafaa5aaSStefano Ceccherini 	direct_sem = create_sem(1, "direct sem");
486cafaa5aaSStefano Ceccherini 	if (direct_sem > 0)
487cafaa5aaSStefano Ceccherini 		dw_init_status |= DW_STATUS_SEM_CREATED;
488cafaa5aaSStefano Ceccherini #endif
489cafaa5aaSStefano Ceccherini 
490cafaa5aaSStefano Ceccherini 	source_clipping_area = sync_data.area;
491cafaa5aaSStefano Ceccherini 	disable_sem = sync_data.disableSem;
492cafaa5aaSStefano Ceccherini 	disable_sem_ack = sync_data.disableSemAck;
493cafaa5aaSStefano Ceccherini 
494cafaa5aaSStefano Ceccherini 	cloned_clipping_area = clone_area("Clone direct area", (void**)&buffer_desc,
495cafaa5aaSStefano Ceccherini 		B_ANY_ADDRESS, B_READ_AREA, source_clipping_area);
4965fdea13fSStefano Ceccherini 
497cafaa5aaSStefano Ceccherini 	if (cloned_clipping_area > 0) {
498cafaa5aaSStefano Ceccherini 		dw_init_status |= DW_STATUS_AREA_CLONED;
499cafaa5aaSStefano Ceccherini 
500cafaa5aaSStefano Ceccherini 		direct_deamon_id = spawn_thread(DirectDeamonFunc, "direct deamon",
501cafaa5aaSStefano Ceccherini 				B_DISPLAY_PRIORITY, this);
502cafaa5aaSStefano Ceccherini 
503cafaa5aaSStefano Ceccherini 		if (direct_deamon_id > 0) {
504cafaa5aaSStefano Ceccherini 			deamon_killer = false;
505cafaa5aaSStefano Ceccherini 			if (resume_thread(direct_deamon_id) == B_OK)
506cafaa5aaSStefano Ceccherini 				dw_init_status |= DW_STATUS_THREAD_STARTED;
507cafaa5aaSStefano Ceccherini 			else
508cafaa5aaSStefano Ceccherini 				kill_thread(direct_deamon_id);
509cafaa5aaSStefano Ceccherini 		}
510cafaa5aaSStefano Ceccherini 	}
511cafaa5aaSStefano Ceccherini }
5120b4a36abSbeveloper 
5130b4a36abSbeveloper 
5140b4a36abSbeveloper void
515cafaa5aaSStefano Ceccherini BDirectWindow::DisposeData()
5160b4a36abSbeveloper {
517cafaa5aaSStefano Ceccherini 	// wait until the connection terminates: we can't destroy
518cafaa5aaSStefano Ceccherini 	// the object until the client receives the B_DIRECT_STOP
519cafaa5aaSStefano Ceccherini 	// notification, or bad things will happen
520cafaa5aaSStefano Ceccherini 	while (connection_enable)
521cafaa5aaSStefano Ceccherini 		snooze(50000);
522cafaa5aaSStefano Ceccherini 
523cafaa5aaSStefano Ceccherini 	LockDirect();
524cafaa5aaSStefano Ceccherini 
525cafaa5aaSStefano Ceccherini 	if (dw_init_status & DW_STATUS_THREAD_STARTED) {
526cafaa5aaSStefano Ceccherini 		deamon_killer = true;
527cafaa5aaSStefano Ceccherini 		// Release this sem, otherwise the Direct deamon thread
528cafaa5aaSStefano Ceccherini 		// will wait forever on it
529cafaa5aaSStefano Ceccherini 		release_sem(disable_sem);
530cafaa5aaSStefano Ceccherini 		status_t retVal;
531cafaa5aaSStefano Ceccherini 		wait_for_thread(direct_deamon_id, &retVal);
532cafaa5aaSStefano Ceccherini 	}
533cafaa5aaSStefano Ceccherini 
534cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
535cafaa5aaSStefano Ceccherini 	if (dw_init_status & DW_STATUS_SEM_CREATED)
536cafaa5aaSStefano Ceccherini 		delete_sem(direct_sem);
537cafaa5aaSStefano Ceccherini #endif
538cafaa5aaSStefano Ceccherini 
539cafaa5aaSStefano Ceccherini 	if (dw_init_status & DW_STATUS_AREA_CLONED)
540cafaa5aaSStefano Ceccherini 		delete_area(cloned_clipping_area);
5410b4a36abSbeveloper }
5420b4a36abSbeveloper 
5430b4a36abSbeveloper 
544cafaa5aaSStefano Ceccherini status_t
545cafaa5aaSStefano Ceccherini BDirectWindow::DriverSetup() const
5460b4a36abSbeveloper {
54717495d0bSStefano Ceccherini 	// Unimplemented in R5.
54809ea3092SStefano Ceccherini 	// This function is probably here because they wanted, in a future time,
54909ea3092SStefano Ceccherini 	// to implement graphic acceleration within BDirectWindow
55009ea3092SStefano Ceccherini 	// (in fact, there is also a BDirectDriver member in BDirectWindow,
55117495d0bSStefano Ceccherini 	// though it's not used).
55209ea3092SStefano Ceccherini 
553cafaa5aaSStefano Ceccherini 	return B_OK;
5540b4a36abSbeveloper }
5550b4a36abSbeveloper 
5560b4a36abSbeveloper 
557cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow1() {}
558cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow2() {}
559cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow3() {}
560cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow4() {}
561