xref: /haiku/src/kits/game/DirectWindow.cpp (revision 366fdcdfbb66b656c588f9573e7e10d804947ed7)
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 
10*366fdcdfSMarcus Overhagen #ifdef COMPILE_FOR_R5
11*366fdcdfSMarcus Overhagen #include "/boot/develop/headers/be/interface/Window.h"
12*366fdcdfSMarcus Overhagen #endif
13*366fdcdfSMarcus Overhagen 
14cafaa5aaSStefano Ceccherini #include <DirectWindow.h>
15cafaa5aaSStefano Ceccherini #include <clipping.h>
160b4a36abSbeveloper 
178575beb8SJérôme Duval #ifdef COMPILE_FOR_R5
18cafaa5aaSStefano Ceccherini #include <R5_AppServerLink.h>
19cafaa5aaSStefano Ceccherini #include <R5_Session.h>
208575beb8SJérôme Duval #endif
2109ea3092SStefano Ceccherini 
22*366fdcdfSMarcus Overhagen // Compiling for DANO/Zeta is broken as it doesn't have BRegion::set_size()
23*366fdcdfSMarcus Overhagen #ifdef COMPILE_FOR_DANO
24*366fdcdfSMarcus Overhagen 		#warning "##### Bilding BDirectWindow for TARGET_PLATFORM=dano (DANO/Zeta) is broken #####"
25*366fdcdfSMarcus Overhagen #endif
26*366fdcdfSMarcus Overhagen 
27*366fdcdfSMarcus Overhagen 
28cafaa5aaSStefano Ceccherini // TODO: We'll want to move this to a private header,
29cafaa5aaSStefano Ceccherini // accessible by the app server.
30cafaa5aaSStefano Ceccherini struct dw_sync_data
310b4a36abSbeveloper {
32cafaa5aaSStefano Ceccherini 	area_id area;
33cafaa5aaSStefano Ceccherini 	sem_id disableSem;
34cafaa5aaSStefano Ceccherini 	sem_id disableSemAck;
35cafaa5aaSStefano Ceccherini };
36cafaa5aaSStefano Ceccherini 
37cafaa5aaSStefano Ceccherini 
3817495d0bSStefano Ceccherini // TODO: These commands are used by the BeOS R5 app_server.
39cafaa5aaSStefano Ceccherini // Change this when our app_server supports BDirectWindow
40cafaa5aaSStefano Ceccherini #define DW_GET_SYNC_DATA		0x880
4109ea3092SStefano Ceccherini #define DW_SET_FULLSCREEN		0x881
42cafaa5aaSStefano Ceccherini #define DW_SUPPORTS_WINDOW_MODE 0xF2C
43cafaa5aaSStefano Ceccherini 
44cafaa5aaSStefano Ceccherini 
45cafaa5aaSStefano Ceccherini // We don't need this kind of locking, since the directDeamonFunc
46cafaa5aaSStefano Ceccherini // doesn't access critical shared data.
47cafaa5aaSStefano Ceccherini #define DW_NEEDS_LOCKING 0
48cafaa5aaSStefano Ceccherini 
49cafaa5aaSStefano Ceccherini enum dw_status_bits {
5017495d0bSStefano Ceccherini 	DW_STATUS_AREA_CLONED	 = 0x1,
5117495d0bSStefano Ceccherini 	DW_STATUS_THREAD_STARTED = 0x2,
5217495d0bSStefano Ceccherini 	DW_STATUS_SEM_CREATED	 = 0x4
53cafaa5aaSStefano Ceccherini };
54cafaa5aaSStefano Ceccherini 
55cafaa5aaSStefano Ceccherini 
56cafaa5aaSStefano Ceccherini BDirectWindow::BDirectWindow(BRect frame, const char *title, window_type type, uint32 flags, uint32 workspace)
57cafaa5aaSStefano Ceccherini 	:BWindow(frame, title, type, flags, workspace)
58cafaa5aaSStefano Ceccherini {
59cafaa5aaSStefano Ceccherini 	InitData();
600b4a36abSbeveloper }
610b4a36abSbeveloper 
620b4a36abSbeveloper 
63cafaa5aaSStefano Ceccherini BDirectWindow::BDirectWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspace)
64cafaa5aaSStefano Ceccherini 	:BWindow(frame, title, look, feel, flags, workspace)
650b4a36abSbeveloper {
66cafaa5aaSStefano Ceccherini 	InitData();
670b4a36abSbeveloper }
680b4a36abSbeveloper 
690b4a36abSbeveloper 
700b4a36abSbeveloper BDirectWindow::~BDirectWindow()
710b4a36abSbeveloper {
72cafaa5aaSStefano Ceccherini 	DisposeData();
730b4a36abSbeveloper }
740b4a36abSbeveloper 
750b4a36abSbeveloper 
76cafaa5aaSStefano Ceccherini // start of regular BWindow API
770b4a36abSbeveloper BArchivable *
780b4a36abSbeveloper BDirectWindow::Instantiate(BMessage *data)
790b4a36abSbeveloper {
800b4a36abSbeveloper 	return NULL;
810b4a36abSbeveloper }
820b4a36abSbeveloper 
830b4a36abSbeveloper 
840b4a36abSbeveloper status_t
85cafaa5aaSStefano Ceccherini BDirectWindow::Archive(BMessage *data, bool deep) const
860b4a36abSbeveloper {
87cafaa5aaSStefano Ceccherini 	return inherited::Archive(data, deep);
880b4a36abSbeveloper }
890b4a36abSbeveloper 
900b4a36abSbeveloper 
910b4a36abSbeveloper void
92cafaa5aaSStefano Ceccherini BDirectWindow::Quit()
930b4a36abSbeveloper {
94cafaa5aaSStefano Ceccherini 	inherited::Quit();
950b4a36abSbeveloper }
960b4a36abSbeveloper 
970b4a36abSbeveloper 
980b4a36abSbeveloper void
99cafaa5aaSStefano Ceccherini BDirectWindow::DispatchMessage(BMessage *message, BHandler *handler)
1000b4a36abSbeveloper {
101cafaa5aaSStefano Ceccherini 	inherited::DispatchMessage(message, handler);
1020b4a36abSbeveloper }
1030b4a36abSbeveloper 
1040b4a36abSbeveloper 
1050b4a36abSbeveloper void
1060b4a36abSbeveloper BDirectWindow::MessageReceived(BMessage *message)
1070b4a36abSbeveloper {
108cafaa5aaSStefano Ceccherini 	inherited::MessageReceived(message);
1090b4a36abSbeveloper }
1100b4a36abSbeveloper 
1110b4a36abSbeveloper 
1120b4a36abSbeveloper void
1130b4a36abSbeveloper BDirectWindow::FrameMoved(BPoint new_position)
1140b4a36abSbeveloper {
115cafaa5aaSStefano Ceccherini 	inherited::FrameMoved(new_position);
1160b4a36abSbeveloper }
1170b4a36abSbeveloper 
1180b4a36abSbeveloper 
1190b4a36abSbeveloper void
120cafaa5aaSStefano Ceccherini BDirectWindow::WorkspacesChanged(uint32 old_ws, uint32 new_ws)
1210b4a36abSbeveloper {
122cafaa5aaSStefano Ceccherini 	inherited::WorkspacesChanged(old_ws, new_ws);
1230b4a36abSbeveloper }
1240b4a36abSbeveloper 
1250b4a36abSbeveloper 
1260b4a36abSbeveloper void
127cafaa5aaSStefano Ceccherini BDirectWindow::WorkspaceActivated(int32 ws, bool state)
1280b4a36abSbeveloper {
129cafaa5aaSStefano Ceccherini 	inherited::WorkspaceActivated(ws, state);
1300b4a36abSbeveloper }
1310b4a36abSbeveloper 
1320b4a36abSbeveloper 
1330b4a36abSbeveloper void
134cafaa5aaSStefano Ceccherini BDirectWindow::FrameResized(float new_width, float new_height)
1350b4a36abSbeveloper {
136cafaa5aaSStefano Ceccherini 	inherited::FrameResized(new_width, new_height);
1370b4a36abSbeveloper }
1380b4a36abSbeveloper 
1390b4a36abSbeveloper 
1400b4a36abSbeveloper void
1410b4a36abSbeveloper BDirectWindow::Minimize(bool minimize)
1420b4a36abSbeveloper {
143cafaa5aaSStefano Ceccherini 	inherited::Minimize(minimize);
1440b4a36abSbeveloper }
1450b4a36abSbeveloper 
1460b4a36abSbeveloper 
1470b4a36abSbeveloper void
148cafaa5aaSStefano Ceccherini BDirectWindow::Zoom(BPoint rec_position, float rec_width, float rec_height)
1490b4a36abSbeveloper {
150cafaa5aaSStefano Ceccherini 	inherited::Zoom(rec_position, rec_width, rec_height);
1510b4a36abSbeveloper }
1520b4a36abSbeveloper 
1530b4a36abSbeveloper 
1540b4a36abSbeveloper void
155cafaa5aaSStefano Ceccherini BDirectWindow::ScreenChanged(BRect screen_size, color_space depth)
1560b4a36abSbeveloper {
157cafaa5aaSStefano Ceccherini 	inherited::ScreenChanged(screen_size, depth);
1580b4a36abSbeveloper }
1590b4a36abSbeveloper 
1600b4a36abSbeveloper 
1610b4a36abSbeveloper void
1620b4a36abSbeveloper BDirectWindow::MenusBeginning()
1630b4a36abSbeveloper {
164cafaa5aaSStefano Ceccherini 	inherited::MenusBeginning();
1650b4a36abSbeveloper }
1660b4a36abSbeveloper 
1670b4a36abSbeveloper 
1680b4a36abSbeveloper void
1690b4a36abSbeveloper BDirectWindow::MenusEnded()
1700b4a36abSbeveloper {
171cafaa5aaSStefano Ceccherini 	inherited::MenusEnded();
1720b4a36abSbeveloper }
1730b4a36abSbeveloper 
1740b4a36abSbeveloper 
1750b4a36abSbeveloper void
1760b4a36abSbeveloper BDirectWindow::WindowActivated(bool state)
1770b4a36abSbeveloper {
178cafaa5aaSStefano Ceccherini 	inherited::WindowActivated(state);
1790b4a36abSbeveloper }
1800b4a36abSbeveloper 
1810b4a36abSbeveloper 
1820b4a36abSbeveloper void
1830b4a36abSbeveloper BDirectWindow::Show()
1840b4a36abSbeveloper {
185cafaa5aaSStefano Ceccherini 	inherited::Show();
1860b4a36abSbeveloper }
1870b4a36abSbeveloper 
1880b4a36abSbeveloper 
1890b4a36abSbeveloper void
1900b4a36abSbeveloper BDirectWindow::Hide()
1910b4a36abSbeveloper {
192cafaa5aaSStefano Ceccherini 	inherited::Hide();
1930b4a36abSbeveloper }
1940b4a36abSbeveloper 
1950b4a36abSbeveloper 
1960b4a36abSbeveloper BHandler *
197cafaa5aaSStefano Ceccherini BDirectWindow::ResolveSpecifier(BMessage *msg, int32 index,
198cafaa5aaSStefano Ceccherini 				BMessage *specifier, int32 form, const char *property)
1990b4a36abSbeveloper {
200cafaa5aaSStefano Ceccherini 	return inherited::ResolveSpecifier(msg, index, specifier, form, property);
2010b4a36abSbeveloper }
2020b4a36abSbeveloper 
2030b4a36abSbeveloper 
2040b4a36abSbeveloper status_t
2050b4a36abSbeveloper BDirectWindow::GetSupportedSuites(BMessage *data)
2060b4a36abSbeveloper {
207cafaa5aaSStefano Ceccherini 	return inherited::GetSupportedSuites(data);
2080b4a36abSbeveloper }
2090b4a36abSbeveloper 
2100b4a36abSbeveloper 
2110b4a36abSbeveloper status_t
212cafaa5aaSStefano Ceccherini BDirectWindow::Perform(perform_code d, void *arg)
2130b4a36abSbeveloper {
214cafaa5aaSStefano Ceccherini 	return inherited::Perform(d, arg);
2150b4a36abSbeveloper }
2160b4a36abSbeveloper 
2170b4a36abSbeveloper 
218b816dc1eSIngo Weinhold void
219b816dc1eSIngo Weinhold BDirectWindow::task_looper()
220b816dc1eSIngo Weinhold {
221cafaa5aaSStefano Ceccherini 	inherited::task_looper();
222b816dc1eSIngo Weinhold }
223b816dc1eSIngo Weinhold 
224cafaa5aaSStefano Ceccherini 
225b816dc1eSIngo Weinhold BMessage *
226b816dc1eSIngo Weinhold BDirectWindow::ConvertToMessage(void *raw, int32 code)
227b816dc1eSIngo Weinhold {
228cafaa5aaSStefano Ceccherini 	return inherited::ConvertToMessage(raw, code);
229b816dc1eSIngo Weinhold }
230cafaa5aaSStefano Ceccherini // end of BWindow API
2310b4a36abSbeveloper 
2320b4a36abSbeveloper 
233cafaa5aaSStefano Ceccherini // BDirectWindow specific API
2340b4a36abSbeveloper void
2350b4a36abSbeveloper BDirectWindow::DirectConnected(direct_buffer_info *info)
2360b4a36abSbeveloper {
237cafaa5aaSStefano Ceccherini 	//implemented in subclasses
2380b4a36abSbeveloper }
2390b4a36abSbeveloper 
2400b4a36abSbeveloper 
2410b4a36abSbeveloper status_t
242cafaa5aaSStefano Ceccherini BDirectWindow::GetClippingRegion(BRegion *region, BPoint *origin) const
2430b4a36abSbeveloper {
244cafaa5aaSStefano Ceccherini 	if (region == NULL)
245cafaa5aaSStefano Ceccherini 		return B_BAD_VALUE;
246cafaa5aaSStefano Ceccherini 
247cafaa5aaSStefano Ceccherini 	if (IsLocked())
248cafaa5aaSStefano Ceccherini 		return B_ERROR;
249cafaa5aaSStefano Ceccherini 
250cafaa5aaSStefano Ceccherini 	if (LockDirect()) {
251cafaa5aaSStefano Ceccherini 		if (in_direct_connect) {
252cafaa5aaSStefano Ceccherini 			UnlockDirect();
253cafaa5aaSStefano Ceccherini 			return B_ERROR;
254cafaa5aaSStefano Ceccherini 		}
255cafaa5aaSStefano Ceccherini 
256cafaa5aaSStefano Ceccherini 		// BPoint's coordinates are floats. We can only work
257cafaa5aaSStefano Ceccherini 		// with integers.
258cafaa5aaSStefano Ceccherini 		int32 originX, originY;
259cafaa5aaSStefano Ceccherini 		if (origin == NULL) {
260cafaa5aaSStefano Ceccherini 			originX = 0;
261cafaa5aaSStefano Ceccherini 			originY = 0;
262cafaa5aaSStefano Ceccherini 		} else {
263cafaa5aaSStefano Ceccherini 			originX = (int32)origin->x;
264cafaa5aaSStefano Ceccherini 			originY = (int32)origin->y;
265cafaa5aaSStefano Ceccherini 		}
266cafaa5aaSStefano Ceccherini 
267*366fdcdfSMarcus Overhagen #ifndef COMPILE_FOR_DANO
268cafaa5aaSStefano Ceccherini 		// Since we are friend of BRegion, we can access its private members.
269cafaa5aaSStefano Ceccherini 		// Otherwise, we would need to call BRegion::Include(clipping_rect)
270cafaa5aaSStefano Ceccherini 		// for every clipping_rect in our clip_list, and that would be much
271cafaa5aaSStefano Ceccherini 		// more overkill than this.
272cafaa5aaSStefano Ceccherini 		region->set_size(buffer_desc->clip_list_count);
273cafaa5aaSStefano Ceccherini 		region->count = buffer_desc->clip_list_count;
274cafaa5aaSStefano Ceccherini 		region->bound = buffer_desc->clip_bounds;
275cafaa5aaSStefano Ceccherini 
276cafaa5aaSStefano Ceccherini 		// adjust bounds by the given origin point
277cafaa5aaSStefano Ceccherini 		offset_rect(region->bound, -originX, -originY);
278cafaa5aaSStefano Ceccherini 
279cafaa5aaSStefano Ceccherini 		for (uint32 c = 0; c < buffer_desc->clip_list_count; c++) {
280cafaa5aaSStefano Ceccherini 			region->data[c] = buffer_desc->clip_list[c];
281cafaa5aaSStefano Ceccherini 			offset_rect(region->data[c], -originX, -originY);
282cafaa5aaSStefano Ceccherini 		}
283cafaa5aaSStefano Ceccherini 
284*366fdcdfSMarcus Overhagen #endif
285*366fdcdfSMarcus Overhagen 
286cafaa5aaSStefano Ceccherini 		UnlockDirect();
287cafaa5aaSStefano Ceccherini 
288cafaa5aaSStefano Ceccherini 		return B_OK;
289cafaa5aaSStefano Ceccherini 	}
290cafaa5aaSStefano Ceccherini 
2910b4a36abSbeveloper 	return B_ERROR;
2920b4a36abSbeveloper }
2930b4a36abSbeveloper 
2940b4a36abSbeveloper 
2950b4a36abSbeveloper status_t
2960b4a36abSbeveloper BDirectWindow::SetFullScreen(bool enable)
2970b4a36abSbeveloper {
298cafaa5aaSStefano Ceccherini 	status_t status = B_ERROR;
29909ea3092SStefano Ceccherini 	if (Lock()) {
3008575beb8SJérôme Duval 
3018575beb8SJérôme Duval #ifdef COMPILE_FOR_R5
30209ea3092SStefano Ceccherini 		a_session->swrite_l(DW_SET_FULLSCREEN);
30309ea3092SStefano Ceccherini 		a_session->swrite_l(server_token);
30417495d0bSStefano Ceccherini 		a_session->swrite_l((int32)enable);
30509ea3092SStefano Ceccherini 		Flush();
30609ea3092SStefano Ceccherini 
307bfc3bb18SStefano Ceccherini 		status_t fullScreen;
308bfc3bb18SStefano Ceccherini 		a_session->sread(sizeof(status_t), &fullScreen);
309bfc3bb18SStefano Ceccherini 		a_session->sread(sizeof(status_t), &status);
3108575beb8SJérôme Duval #endif
31109ea3092SStefano Ceccherini 		Unlock();
312bfc3bb18SStefano Ceccherini 
3133f9ae8a3SStefano Ceccherini 		// TODO: Revisit this when we move to our app_server
3143f9ae8a3SStefano Ceccherini 		// Currently the full screen/window status is set
3153f9ae8a3SStefano Ceccherini 		// even if something goes wrong
3163f9ae8a3SStefano Ceccherini 		full_screen_enable = enable;
31709ea3092SStefano Ceccherini 	}
318cafaa5aaSStefano Ceccherini 	return status;
3190b4a36abSbeveloper }
3200b4a36abSbeveloper 
3210b4a36abSbeveloper 
3220b4a36abSbeveloper bool
3230b4a36abSbeveloper BDirectWindow::IsFullScreen() const
3240b4a36abSbeveloper {
325cafaa5aaSStefano Ceccherini 	return full_screen_enable;
3260b4a36abSbeveloper }
3270b4a36abSbeveloper 
3280b4a36abSbeveloper 
3290b4a36abSbeveloper bool
330cafaa5aaSStefano Ceccherini BDirectWindow::SupportsWindowMode(screen_id id)
3310b4a36abSbeveloper {
3328575beb8SJérôme Duval 	int32 result = 0;
3338575beb8SJérôme Duval 
3348575beb8SJérôme Duval #ifdef COMPILE_FOR_R5
335cafaa5aaSStefano Ceccherini 	_BAppServerLink_ link;
336cafaa5aaSStefano Ceccherini 	link.fSession->swrite_l(DW_SUPPORTS_WINDOW_MODE);
337cafaa5aaSStefano Ceccherini 	link.fSession->swrite_l(id.id);
338cafaa5aaSStefano Ceccherini 	link.fSession->sync();
339cafaa5aaSStefano Ceccherini 	link.fSession->sread(sizeof(result), &result);
3408575beb8SJérôme Duval #endif
341cafaa5aaSStefano Ceccherini 
342cafaa5aaSStefano Ceccherini 	return result & true;
343cafaa5aaSStefano Ceccherini }
344cafaa5aaSStefano Ceccherini 
345cafaa5aaSStefano Ceccherini 
346cafaa5aaSStefano Ceccherini // Private methods
347cafaa5aaSStefano Ceccherini int32
348cafaa5aaSStefano Ceccherini BDirectWindow::DirectDeamonFunc(void *arg)
349cafaa5aaSStefano Ceccherini {
350cafaa5aaSStefano Ceccherini 	BDirectWindow *object = static_cast<BDirectWindow *>(arg);
351cafaa5aaSStefano Ceccherini 
352cafaa5aaSStefano Ceccherini 	while (!object->deamon_killer) {
353cafaa5aaSStefano Ceccherini 		// This sem is released by the app_server when our
354cafaa5aaSStefano Ceccherini 		// clipping region changes, or when our window is moved,
355cafaa5aaSStefano Ceccherini 		// resized, etc. etc.
356cafaa5aaSStefano Ceccherini 		while (acquire_sem(object->disable_sem) == B_INTERRUPTED)
357cafaa5aaSStefano Ceccherini 			;
358cafaa5aaSStefano Ceccherini 
359cafaa5aaSStefano Ceccherini 		if (object->LockDirect()) {
360cafaa5aaSStefano Ceccherini 			if ((object->buffer_desc->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_START)
361cafaa5aaSStefano Ceccherini 				object->connection_enable = true;
362cafaa5aaSStefano Ceccherini 
363cafaa5aaSStefano Ceccherini 			object->in_direct_connect = true;
364cafaa5aaSStefano Ceccherini 			object->DirectConnected(object->buffer_desc);
365cafaa5aaSStefano Ceccherini 			object->in_direct_connect = false;
366cafaa5aaSStefano Ceccherini 
367cafaa5aaSStefano Ceccherini 			if ((object->buffer_desc->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP)
368cafaa5aaSStefano Ceccherini 				object->connection_enable = false;
369cafaa5aaSStefano Ceccherini 
370cafaa5aaSStefano Ceccherini 			object->UnlockDirect();
371cafaa5aaSStefano Ceccherini 		}
372cafaa5aaSStefano Ceccherini 
373cafaa5aaSStefano Ceccherini 		// The app_server then waits (with a timeout) on this sem.
374cafaa5aaSStefano Ceccherini 		// If we aren't quick enough to release this sem, our app
375cafaa5aaSStefano Ceccherini 		// will be terminated by the app_server
376cafaa5aaSStefano Ceccherini 		release_sem(object->disable_sem_ack);
377cafaa5aaSStefano Ceccherini 	}
378cafaa5aaSStefano Ceccherini 
379cafaa5aaSStefano Ceccherini 	return 0;
380cafaa5aaSStefano Ceccherini }
381cafaa5aaSStefano Ceccherini 
382cafaa5aaSStefano Ceccherini 
38317495d0bSStefano Ceccherini // LockDirect() and UnlockDirect() are no-op on R5. I tried to call (R5's) LockDirect()
38417495d0bSStefano Ceccherini // repeatedly, from the same thread and from different threads, nothing happened.
38517495d0bSStefano Ceccherini // I implemented them anyway, as they were the first methods I wrote
38617495d0bSStefano Ceccherini // in this class (As you can see, I even needed to cast away their constness
38717495d0bSStefano Ceccherini // to make them do something useful).
38817495d0bSStefano Ceccherini // They're not needed though, as the direct_deamon_thread doesn't change
38917495d0bSStefano Ceccherini // any shared data. They are probably here for future enhancements (see also the
39017495d0bSStefano Ceccherini // comment in DriverSetup()
391cafaa5aaSStefano Ceccherini bool
392cafaa5aaSStefano Ceccherini BDirectWindow::LockDirect() const
393cafaa5aaSStefano Ceccherini {
394cafaa5aaSStefano Ceccherini 	status_t status = B_OK;
395cafaa5aaSStefano Ceccherini 
396cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
397cafaa5aaSStefano Ceccherini 	BDirectWindow *casted = const_cast<BDirectWindow *>(this);
398cafaa5aaSStefano Ceccherini 
399cafaa5aaSStefano Ceccherini 	if (atomic_add(&casted->direct_lock, 1) > 0)
400cafaa5aaSStefano Ceccherini 		do {
401cafaa5aaSStefano Ceccherini 			status = acquire_sem(direct_sem);
402cafaa5aaSStefano Ceccherini 		} while (status == B_INTERRUPTED);
403cafaa5aaSStefano Ceccherini 
404cafaa5aaSStefano Ceccherini 	if (status == B_OK) {
405cafaa5aaSStefano Ceccherini 		casted->direct_lock_owner = find_thread(NULL);
406cafaa5aaSStefano Ceccherini 		casted->direct_lock_count++;
407cafaa5aaSStefano Ceccherini 	}
408cafaa5aaSStefano Ceccherini #endif
409cafaa5aaSStefano Ceccherini 
410cafaa5aaSStefano Ceccherini 	return status == B_OK;
4110b4a36abSbeveloper }
4120b4a36abSbeveloper 
4130b4a36abSbeveloper 
4140b4a36abSbeveloper void
415cafaa5aaSStefano Ceccherini BDirectWindow::UnlockDirect() const
4160b4a36abSbeveloper {
417cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
418cafaa5aaSStefano Ceccherini 	BDirectWindow *casted = const_cast<BDirectWindow *>(this);
419cafaa5aaSStefano Ceccherini 
420cafaa5aaSStefano Ceccherini 	if (atomic_add(&casted->direct_lock, -1) > 1)
421cafaa5aaSStefano Ceccherini 		release_sem(direct_sem);
422cafaa5aaSStefano Ceccherini 
423cafaa5aaSStefano Ceccherini 	casted->direct_lock_count--;
424cafaa5aaSStefano Ceccherini #endif
4250b4a36abSbeveloper }
4260b4a36abSbeveloper 
4270b4a36abSbeveloper 
4280b4a36abSbeveloper void
429cafaa5aaSStefano Ceccherini BDirectWindow::InitData()
4300b4a36abSbeveloper {
431cafaa5aaSStefano Ceccherini 	connection_enable = false;
432cafaa5aaSStefano Ceccherini 	full_screen_enable = false;
433cafaa5aaSStefano Ceccherini 	in_direct_connect = false;
434cafaa5aaSStefano Ceccherini 
435cafaa5aaSStefano Ceccherini 	dw_init_status = 0;
436cafaa5aaSStefano Ceccherini 
437cafaa5aaSStefano Ceccherini 	direct_driver_ready = false;
438cafaa5aaSStefano Ceccherini 	direct_driver_type = 0;
439cafaa5aaSStefano Ceccherini 	direct_driver_token = 0;
440cafaa5aaSStefano Ceccherini 	direct_driver = NULL;
441cafaa5aaSStefano Ceccherini 
442cafaa5aaSStefano Ceccherini 	if (Lock()) {
4438575beb8SJérôme Duval 		struct dw_sync_data sync_data;
4448575beb8SJérôme Duval 		status_t status = B_ERROR;
4458575beb8SJérôme Duval 
4468575beb8SJérôme Duval #ifdef COMPILE_FOR_R5
447cafaa5aaSStefano Ceccherini 		a_session->swrite_l(DW_GET_SYNC_DATA);
448cafaa5aaSStefano Ceccherini 		a_session->swrite_l(server_token);
4498575beb8SJérôme Duval 
450cafaa5aaSStefano Ceccherini 		Flush();
451cafaa5aaSStefano Ceccherini 
452cafaa5aaSStefano Ceccherini 		a_session->sread(sizeof(sync_data), &sync_data);
453cafaa5aaSStefano Ceccherini 
454cafaa5aaSStefano Ceccherini 
4558575beb8SJérôme Duval 		a_session->sread(sizeof(status), &status);
4568575beb8SJérôme Duval #endif
457cafaa5aaSStefano Ceccherini 		Unlock();
458cafaa5aaSStefano Ceccherini 
459cafaa5aaSStefano Ceccherini 		if (status == B_OK) {
460cafaa5aaSStefano Ceccherini 
461cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
462cafaa5aaSStefano Ceccherini 			direct_lock = 0;
463cafaa5aaSStefano Ceccherini 			direct_lock_count = 0;
464cafaa5aaSStefano Ceccherini 			direct_lock_owner = B_ERROR;
465cafaa5aaSStefano Ceccherini 			direct_lock_stack = NULL;
466cafaa5aaSStefano Ceccherini 			direct_sem = create_sem(1, "direct sem");
467cafaa5aaSStefano Ceccherini 			if (direct_sem > 0)
468cafaa5aaSStefano Ceccherini 				dw_init_status |= DW_STATUS_SEM_CREATED;
469cafaa5aaSStefano Ceccherini #endif
470cafaa5aaSStefano Ceccherini 
471cafaa5aaSStefano Ceccherini 			source_clipping_area = sync_data.area;
472cafaa5aaSStefano Ceccherini 			disable_sem = sync_data.disableSem;
473cafaa5aaSStefano Ceccherini 			disable_sem_ack = sync_data.disableSemAck;
474cafaa5aaSStefano Ceccherini 
475cafaa5aaSStefano Ceccherini 			cloned_clipping_area = clone_area("Clone direct area", (void**)&buffer_desc,
476cafaa5aaSStefano Ceccherini 				B_ANY_ADDRESS, B_READ_AREA, source_clipping_area);
477cafaa5aaSStefano Ceccherini 			if (cloned_clipping_area > 0) {
478cafaa5aaSStefano Ceccherini 				dw_init_status |= DW_STATUS_AREA_CLONED;
479cafaa5aaSStefano Ceccherini 
480cafaa5aaSStefano Ceccherini 				direct_deamon_id = spawn_thread(DirectDeamonFunc, "direct deamon",
481cafaa5aaSStefano Ceccherini 					B_DISPLAY_PRIORITY, this);
482cafaa5aaSStefano Ceccherini 
483cafaa5aaSStefano Ceccherini 				if (direct_deamon_id > 0) {
484cafaa5aaSStefano Ceccherini 					deamon_killer = false;
485cafaa5aaSStefano Ceccherini 					if (resume_thread(direct_deamon_id) == B_OK)
486cafaa5aaSStefano Ceccherini 						dw_init_status |= DW_STATUS_THREAD_STARTED;
487cafaa5aaSStefano Ceccherini 					else
488cafaa5aaSStefano Ceccherini 						kill_thread(direct_deamon_id);
489cafaa5aaSStefano Ceccherini 				}
490cafaa5aaSStefano Ceccherini 			}
491cafaa5aaSStefano Ceccherini 		}
492cafaa5aaSStefano Ceccherini 	}
4930b4a36abSbeveloper }
4940b4a36abSbeveloper 
4950b4a36abSbeveloper 
4960b4a36abSbeveloper void
497cafaa5aaSStefano Ceccherini BDirectWindow::DisposeData()
4980b4a36abSbeveloper {
499cafaa5aaSStefano Ceccherini 	// wait until the connection terminates: we can't destroy
500cafaa5aaSStefano Ceccherini 	// the object until the client receives the B_DIRECT_STOP
501cafaa5aaSStefano Ceccherini 	// notification, or bad things will happen
502cafaa5aaSStefano Ceccherini 	while (connection_enable)
503cafaa5aaSStefano Ceccherini 		snooze(50000);
504cafaa5aaSStefano Ceccherini 
505cafaa5aaSStefano Ceccherini 	LockDirect();
506cafaa5aaSStefano Ceccherini 
507cafaa5aaSStefano Ceccherini 	if (dw_init_status & DW_STATUS_THREAD_STARTED) {
508cafaa5aaSStefano Ceccherini 		deamon_killer = true;
509cafaa5aaSStefano Ceccherini 		// Release this sem, otherwise the Direct deamon thread
510cafaa5aaSStefano Ceccherini 		// will wait forever on it
511cafaa5aaSStefano Ceccherini 		release_sem(disable_sem);
512cafaa5aaSStefano Ceccherini 		status_t retVal;
513cafaa5aaSStefano Ceccherini 		wait_for_thread(direct_deamon_id, &retVal);
514cafaa5aaSStefano Ceccherini 	}
515cafaa5aaSStefano Ceccherini 
516cafaa5aaSStefano Ceccherini #if DW_NEEDS_LOCKING
517cafaa5aaSStefano Ceccherini 	if (dw_init_status & DW_STATUS_SEM_CREATED)
518cafaa5aaSStefano Ceccherini 		delete_sem(direct_sem);
519cafaa5aaSStefano Ceccherini #endif
520cafaa5aaSStefano Ceccherini 
521cafaa5aaSStefano Ceccherini 	if (dw_init_status & DW_STATUS_AREA_CLONED)
522cafaa5aaSStefano Ceccherini 		delete_area(cloned_clipping_area);
5230b4a36abSbeveloper }
5240b4a36abSbeveloper 
5250b4a36abSbeveloper 
526cafaa5aaSStefano Ceccherini status_t
527cafaa5aaSStefano Ceccherini BDirectWindow::DriverSetup() const
5280b4a36abSbeveloper {
52917495d0bSStefano Ceccherini 	// Unimplemented in R5.
53009ea3092SStefano Ceccherini 	// This function is probably here because they wanted, in a future time,
53109ea3092SStefano Ceccherini 	// to implement graphic acceleration within BDirectWindow
53209ea3092SStefano Ceccherini 	// (in fact, there is also a BDirectDriver member in BDirectWindow,
53317495d0bSStefano Ceccherini 	// though it's not used).
53409ea3092SStefano Ceccherini 
535cafaa5aaSStefano Ceccherini 	return B_OK;
5360b4a36abSbeveloper }
5370b4a36abSbeveloper 
5380b4a36abSbeveloper 
539cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow1() {}
540cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow2() {}
541cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow3() {}
542cafaa5aaSStefano Ceccherini void BDirectWindow::_ReservedDirectWindow4() {}
543