xref: /haiku/src/kits/game/WindowScreen.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2  * Copyright 2002-2004,
3  * Marcus Overhagen,
4  * Stefano Ceccherini (burton666@libero.it),
5  * Carwyn Jones (turok2@currantbun.com)
6  * All rights reserved.
7  * Distributed under the terms of the MIT License.
8  */
9 
10 #include <Application.h>
11 #include <Screen.h>
12 #include <WindowScreen.h>
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include "R5_AppServerLink.h"
19 
20 // WindowScreen commands
21 #define WS_PROPOSE_MODE			0x00000102
22 #define WS_MOVE_DISPLAY			0x00000108
23 #define WS_GET_FRAMEBUFFER 		0x00000eed
24 #define WS_GET_ACCELERANT_NAME 	0x00000ef4
25 #define WS_GET_DRIVER_NAME 		0x00000ef5
26 #define WS_GET_DISPLAY_MODE 	0x00000efd
27 #define WS_DISPLAY_UTILS		0x00000ef9
28 #define WS_SWITCH_WORKSPACE 	0x00000f26
29 #define WS_SET_PALETTE			0x00000f27
30 #define WS_SET_FULLSCREEN 		0x00000881
31 
32 
33 static const uint32 WS_SET_MOUSE_POSITION = 'Ismp';
34 
35 
36 // WindowScreen Window flag (not defined anywhere else)
37 #define WS_SPECIAL_FLAG			0x10000
38 
39 
40 #if TRACE_WINDOWSCREEN
41 #define CALLED() printf("%s\n", __PRETTY_FUNCTION__);
42 #else
43 #define CALLED() ;
44 #endif
45 
46 // TODO: Move this declaration somewhere else
47 _IMPEXP_BE status_t _control_input_server_(BMessage *command, BMessage *reply);
48 
49 static graphics_card_info card_info_global;
50 fill_rectangle fill_rect_global;
51 screen_to_screen_blit blit_rect_global;
52 screen_to_screen_transparent_blit trans_blit_rect_global;
53 screen_to_screen_scaled_filtered_blit scaled_filtered_blit_rect_global;
54 wait_engine_idle wait_idle_global;
55 engine_token *et_global;
56 acquire_engine acquire_engine_global;
57 release_engine release_engine_global;
58 
59 
60 // Helper methods which translates the pre r5 graphics methods to r5 ones
61 static int32
62 sync()
63 {
64 	wait_idle_global();
65 	return 0;
66 }
67 
68 
69 static int32
70 blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width, int32 height)
71 {
72 	blit_params param;
73 	param.src_left = sx;
74 	param.src_top = sy;
75 	param.dest_left = dx;
76 	param.dest_top = dy;
77 	param.width = width;
78 	param.height = height;
79 
80 	acquire_engine_global(1, 0xff, 0, &et_global);
81 	blit_rect_global(et_global, &param, 1);
82 	release_engine_global(et_global, 0);
83 	return 0;
84 }
85 
86 
87 static int32
88 transparent_blit(int32 sx, int32 sy, int32 dx, int32 dy,
89 			int32 width, int32 height, uint32 transparent_color)
90 {
91 	blit_params param;
92 	param.src_left = sx;
93 	param.src_top = sy;
94 	param.dest_left = dx;
95 	param.dest_top = dy;
96 	param.width = width;
97 	param.height = height;
98 
99 	acquire_engine_global(1, 0xff, 0, &et_global);
100 	trans_blit_rect_global(et_global, transparent_color, &param, 1);
101 	release_engine_global(et_global, 0);
102 	return 0;
103 }
104 
105 
106 static int32
107 scaled_filtered_blit(int32 sx, int32 sy, int32 sw, int32 sh, int32 dx, int32 dy, int32 dw, int32 dh)
108 {
109 	scaled_blit_params param;
110 	param.src_left = sx;
111 	param.src_top = sy;
112 	param.src_width = sw;
113 	param.src_height = sh;
114 	param.dest_left = dx;
115 	param.dest_top = dy;
116 	param.dest_width = dw;
117 	param.dest_height = dh;
118 
119 	acquire_engine_global(1, 0xff, 0, &et_global);
120 	scaled_filtered_blit_rect_global(et_global, &param, 1);
121 	release_engine_global(et_global, 0);
122 	return 0;
123 }
124 
125 
126 static int32
127 draw_rect_8(int32 sx, int32 sy, int32 sw, int32 sh, uint8 color_index)
128 {
129 	fill_rect_params param;
130 	param.left = sx;
131 	param.top = sy;
132 	param.right = sw;
133 	param.bottom = sh;
134 
135 	acquire_engine_global(1, 0xff, 0, &et_global);
136 	fill_rect_global(et_global, color_index, &param, 1);
137 	release_engine_global(et_global, 0);
138 	return 0;
139 }
140 
141 
142 static int32
143 draw_rect_16(int32 sx, int32 sy, int32 sw, int32 sh, uint16 color)
144 {
145 	fill_rect_params param;
146 	param.left = sx;
147 	param.top = sy;
148 	param.right = sw;
149 	param.bottom = sh;
150 
151 	acquire_engine_global(1, 0xff, 0, &et_global);
152 	fill_rect_global(et_global, color, &param, 1);
153 	release_engine_global(et_global, 0);
154 	return 0;
155 }
156 
157 
158 static int32
159 draw_rect_32(int32 sx, int32 sy, int32 sw, int32 sh, uint32 color)
160 {
161 	fill_rect_params param;
162 	param.left = sx;
163 	param.top = sy;
164 	param.right = sw;
165 	param.bottom = sh;
166 
167 	acquire_engine_global(1, 0xff, 0, &et_global);
168 	fill_rect_global(et_global, color, &param, 1);
169 	release_engine_global(et_global, 0);
170 	return 0;
171 }
172 
173 
174 static void
175 mode2parms(uint32 space, uint32 *out_space, int32 *width, int32 *height)
176 {
177 	switch (space) {
178 		case B_8_BIT_640x480:
179 			*out_space = B_CMAP8;
180 			*width = 640; *height = 480;
181 			break;
182 		case B_8_BIT_800x600:
183 			*out_space = B_CMAP8;
184 			*width = 800; *height = 600;
185 			break;
186 		case B_8_BIT_1024x768:
187 			*out_space = B_CMAP8;
188 			*width = 1024; *height = 768;
189 			break;
190 		case B_8_BIT_1280x1024:
191 			*out_space = B_CMAP8;
192 			*width = 1280; *height = 1024;
193 			break;
194 		case B_8_BIT_1600x1200:
195 			*out_space = B_CMAP8;
196 			*width = 1600; *height = 1200;
197 			break;
198 		case B_16_BIT_640x480:
199 			*out_space = B_RGB16;
200 			*width = 640; *height = 480;
201 			break;
202 		case B_16_BIT_800x600:
203 			*out_space = B_RGB16;
204 			*width = 800; *height = 600;
205 			break;
206 		case B_16_BIT_1024x768:
207 			*out_space = B_RGB16;
208 			*width = 1024; *height = 768;
209 			break;
210 		case B_16_BIT_1280x1024:
211 			*out_space = B_RGB16;
212 			*width = 1280; *height = 1024;
213 			break;
214 		case B_16_BIT_1600x1200:
215 			*out_space = B_RGB16;
216 			*width = 1600; *height = 1200;
217 			break;
218 		case B_32_BIT_640x480:
219 			*out_space = B_RGB32;
220 			*width = 640; *height = 480;
221 			break;
222 		case B_32_BIT_800x600:
223 			*out_space = B_RGB32;
224 			*width = 800; *height = 600;
225 			break;
226 		case B_32_BIT_1024x768:
227 			*out_space = B_RGB32;
228 			*width = 1024; *height = 768;
229 			break;
230 		case B_32_BIT_1280x1024:
231 			*out_space = B_RGB32;
232 			*width = 1280; *height = 1024;
233 			break;
234 		case B_32_BIT_1600x1200:
235 			*out_space = B_RGB32;
236 			*width = 1600; *height = 1200;
237 			break;
238     	case B_8_BIT_1152x900:
239     		*out_space = B_CMAP8;
240     		*width = 1152; *height = 900;
241     		break;
242     	case B_16_BIT_1152x900:
243     		*out_space = B_RGB16;
244     		*width = 1152; *height = 900;
245     		break;
246     	case B_32_BIT_1152x900:
247     		*out_space = B_RGB32;
248     		*width = 1152; *height = 900;
249     		break;
250 		case B_15_BIT_640x480:
251 			*out_space = B_RGB15;
252 			*width = 640; *height = 480;
253 			break;
254 		case B_15_BIT_800x600:
255 			*out_space = B_RGB15;
256 			*width = 800; *height = 600;
257 			break;
258 		case B_15_BIT_1024x768:
259 			*out_space = B_RGB15;
260 			*width = 1024; *height = 768;
261 			break;
262 		case B_15_BIT_1280x1024:
263 			*out_space = B_RGB15;
264 			*width = 1280; *height = 1024;
265 			break;
266 		case B_15_BIT_1600x1200:
267 			*out_space = B_RGB15;
268 			*width = 1600; *height = 1200;
269 			break;
270     	case B_15_BIT_1152x900:
271     		*out_space = B_RGB15;
272     		*width = 1152; *height = 900;
273     		break;
274 	}
275 }
276 
277 
278 // BWindowScreen public API
279 
280 void
281 set_mouse_position(int32 x, int32 y)
282 {
283 	BMessage command(WS_SET_MOUSE_POSITION);
284 	BMessage reply;
285 
286 	command.AddPoint("where", BPoint(x, y));
287 	_control_input_server_(&command, &reply);
288 }
289 
290 
291 BWindowScreen::BWindowScreen(const char *title, uint32 space, status_t *error, bool debug_enable)
292 	:
293 	BWindow(BScreen().Frame(), title, B_TITLED_WINDOW,
294 		WS_SPECIAL_FLAG | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE,
295 		B_CURRENT_WORKSPACE)
296 {
297 	CALLED();
298 	uint32 attributes = 0;
299 	if (debug_enable)
300 		attributes |= B_ENABLE_DEBUGGER;
301 
302 	*error = InitData(space, attributes);
303 }
304 
305 
306 BWindowScreen::BWindowScreen(const char *title, uint32 space, uint32 attributes, status_t *error)
307 	:
308 	BWindow(BScreen().Frame(), title, B_TITLED_WINDOW,
309 		WS_SPECIAL_FLAG | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE,
310 		B_CURRENT_WORKSPACE)
311 {
312 	CALLED();
313 	*error = InitData(space, attributes);
314 }
315 
316 
317 BWindowScreen::~BWindowScreen()
318 {
319 	Disconnect();
320 	if (addon_state == 1)
321 		unload_add_on(addon_image);
322 
323 	SetFullscreen(0);
324 
325 	delete_sem(activate_sem);
326 	delete_sem(debug_sem);
327 
328 	if (debug_state) {
329 		_BAppServerLink_ link;
330 		link.fSession->swrite_l(WS_SWITCH_WORKSPACE);
331 		link.fSession->swrite_l(debug_workspace);
332 		link.fSession->sync();
333 	}
334 
335 	free(new_space);
336 	free(old_space);
337 	free(mode_list);
338 }
339 
340 
341 void
342 BWindowScreen::Quit(void)
343 {
344 	Disconnect();
345 	BWindow::Quit();
346 }
347 
348 
349 void
350 BWindowScreen::ScreenConnected(bool active)
351 {
352 	// Implemented in subclasses
353 }
354 
355 
356 void
357 BWindowScreen::Disconnect()
358 {
359 	if (lock_state == 1) {
360 		if (debug_state)
361 			debug_first = true;
362 		SetActiveState(0);
363 	}
364 }
365 
366 void
367 BWindowScreen::WindowActivated(bool active)
368 {
369 	window_state = active;
370 	if(active && lock_state == 0 && work_state)
371 		SetActiveState(1);
372 }
373 
374 void
375 BWindowScreen::WorkspaceActivated(int32 ws,
376 								  bool state)
377 {
378 	work_state = state;
379 	if (state) {
380 		if (lock_state == 0 && window_state) {
381 			SetActiveState(1);
382 			if (!IsHidden()) {
383 				Activate(true);
384 				WindowActivated(true);
385 			}
386 		}
387 	} else {
388 		if (lock_state)
389 			SetActiveState(0);
390 	}
391 }
392 
393 
394 void
395 BWindowScreen::ScreenChanged(BRect screen_size, color_space depth)
396 {
397 	// Implemented in subclasses
398 }
399 
400 
401 void
402 BWindowScreen::Hide()
403 {
404 	if (lock_state == 1) {
405 		if (debug_state)
406 			debug_first = true;
407 		SetActiveState(0);
408 	}
409 
410 	BWindow::Hide();
411 }
412 
413 
414 void
415 BWindowScreen::Show()
416 {
417 	BWindow::Show();
418 	if (!activate_state) {
419 		release_sem(activate_sem);
420 		activate_state = true;
421 	}
422 }
423 
424 
425 void
426 BWindowScreen::SetColorList(rgb_color *list, int32 first_index, int32 last_index)
427 {
428 	if (first_index < 0 || last_index > 255 || first_index > last_index)
429 		return;
430 
431 	if (Lock()) {
432 		if (!activate_state) {
433 			//If we aren't active, we just change our local palette
434 			for (int32 x = first_index; x <= last_index; x++)
435 				colorList[x] = list[x];
436 		} else {
437 			uint32 colorCount = last_index - first_index + 1;
438 			if (addon_state == 1) {
439 				set_indexed_colors sic = (set_indexed_colors)m_gah(B_SET_INDEXED_COLORS, NULL);
440 				if (sic != NULL)
441 					sic(colorCount, first_index, (uint8*)colorList, 0);
442 			}
443 
444 			BScreen screen(this);
445 			screen.WaitForRetrace();
446 			// Update our local palette too. We're doing this between two
447 			// WaitForRetrace() calls so nobody will notice.
448 			for (int32 x = first_index; x <= last_index; x++)
449 				colorList[x] = list[x];
450 
451 			// Tell the app_server about our changes
452 			_BAppServerLink_ link;
453 			link.fSession->swrite_l(WS_SET_PALETTE);
454 			link.fSession->swrite_l(screen_index);
455 			link.fSession->swrite_l(first_index);
456 			link.fSession->swrite_l(last_index);
457 			link.fSession->swrite(colorCount * sizeof(rgb_color), colorList);
458 			link.fSession->sync();
459 
460 			screen.WaitForRetrace();
461 		}
462 
463 		Unlock();
464 	}
465 }
466 
467 
468 status_t
469 BWindowScreen::SetSpace(uint32 space)
470 {
471 	display_mode mode;
472 	status_t status = GetModeFromSpace(space, &mode);
473 	if (status == B_OK)
474 		status = AssertDisplayMode(&mode);
475 	return status;
476 }
477 
478 
479 bool
480 BWindowScreen::CanControlFrameBuffer()
481 {
482 	bool retval = false;
483 	if (addon_state <= 1 && (card_info.flags & B_FRAME_BUFFER_CONTROL))
484 		retval = true;
485 
486 	return retval;
487 }
488 
489 
490 status_t
491 BWindowScreen::SetFrameBuffer(int32 width, int32 height)
492 {
493 	display_mode highMode = *new_space;
494 
495 	highMode.virtual_height = (int16)height;
496 	highMode.virtual_width = (int16)width;
497 
498 	display_mode lowMode = highMode;
499 	display_mode mode = highMode;
500 
501 	// equivalent to BScreen::ProposeMode()
502 	_BAppServerLink_ link;
503 	link.fSession->swrite_l(WS_DISPLAY_UTILS);
504 	link.fSession->swrite_l(screen_index);
505 	link.fSession->swrite_l(WS_PROPOSE_MODE);
506 	link.fSession->swrite(sizeof(display_mode), &highMode);
507 	link.fSession->swrite(sizeof(display_mode), &mode);
508 	link.fSession->swrite(sizeof(display_mode), &lowMode);
509 	link.fSession->sync();
510 
511 	status_t status;
512 	link.fSession->sread(sizeof(status), &status);
513 	link.fSession->sread(sizeof(display_mode), &mode);
514 
515 	// If the mode is supported, change the workspace
516 	// to that mode.
517 	if (status == B_OK)
518 		status = AssertDisplayMode(&mode);
519 
520 	return status;
521 }
522 
523 
524 status_t
525 BWindowScreen::MoveDisplayArea(int32 x, int32 y)
526 {
527 	_BAppServerLink_ link;
528 	link.fSession->swrite_l(WS_DISPLAY_UTILS);
529 	link.fSession->swrite_l(screen_index);
530 	link.fSession->swrite_l(WS_MOVE_DISPLAY);
531 	link.fSession->swrite(sizeof(int16), (int16*)&x);
532 	link.fSession->swrite(sizeof(int16), (int16*)&y);
533 	link.fSession->sync();
534 
535 	status_t status;
536 	link.fSession->sread(sizeof(status), &status);
537 
538 	if (status == B_OK) {
539 		format_info.display_x = x;
540 		format_info.display_y = y;
541 		new_space->h_display_start = x;
542 		new_space->v_display_start = y;
543 	}
544 	return status;
545 }
546 
547 
548 void *
549 BWindowScreen::IOBase()
550 {
551 	// Not supported
552 	return NULL;
553 }
554 
555 
556 rgb_color *
557 BWindowScreen::ColorList()
558 {
559 	return colorList;
560 }
561 
562 
563 frame_buffer_info *
564 BWindowScreen::FrameBufferInfo()
565 {
566 	return &format_info;
567 }
568 
569 
570 graphics_card_hook
571 BWindowScreen::CardHookAt(int32 index)
572 {
573 	if (addon_state != 1)
574 		return 0;
575 
576 	graphics_card_hook hook = NULL;
577 
578 	switch (index) {
579 		case 5: // 8 bit fill rect
580 			hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0);
581 			fill_rect = (fill_rectangle)hook;
582 			fill_rect_global = fill_rect;
583 			hook = (graphics_card_hook)draw_rect_8;
584 			break;
585 		case 6: // 32 bit fill rect
586 			hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0);
587 			fill_rect = (fill_rectangle)hook;
588 			fill_rect_global = fill_rect;
589 			hook = (graphics_card_hook)draw_rect_32;
590 			break;
591 		case 7: // screen to screen blit
592 			hook = (graphics_card_hook)m_gah(B_SCREEN_TO_SCREEN_BLIT, 0);
593 			blit_rect = (screen_to_screen_blit)hook;
594 			blit_rect_global = blit_rect;
595 			hook = (graphics_card_hook)blit;
596 			break;
597 		case 8: // screen to screen scaled filtered blit
598 			hook = (graphics_card_hook)m_gah(B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT, 0);
599 			scaled_filtered_blit_rect = (screen_to_screen_scaled_filtered_blit)hook;
600 			scaled_filtered_blit_rect_global = scaled_filtered_blit_rect;
601 			hook = (graphics_card_hook)scaled_filtered_blit;
602 			break;
603 		case 10: // sync aka wait for graphics card idle
604 			hook = (graphics_card_hook)sync;
605 			break;
606 		case 13: // 16 bit fill rect
607 			hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0);
608 			fill_rect = (fill_rectangle)hook;
609 			fill_rect_global = fill_rect;
610 			hook = (graphics_card_hook)draw_rect_16;
611 			break;
612 		default:
613 			break;
614 	}
615 
616 	return hook;
617 }
618 
619 
620 graphics_card_info *
621 BWindowScreen::CardInfo()
622 {
623 	return &card_info;
624 }
625 
626 
627 void
628 BWindowScreen::RegisterThread(thread_id id)
629 {
630 	CALLED();
631 	while (acquire_sem(debug_sem) == B_INTERRUPTED)
632 		;
633 	++debug_list_count;
634 	debug_list = (thread_id *)realloc(debug_list, debug_list_count * sizeof(thread_id));
635 	debug_list[debug_list_count - 1] = id;
636 
637 	release_sem(debug_sem);
638 }
639 
640 
641 void
642 BWindowScreen::SuspensionHook(bool active)
643 {
644 	// Implemented in subclasses
645 }
646 
647 
648 void
649 BWindowScreen::Suspend(char *label)
650 {
651 	CALLED();
652 	if (debug_state) {
653 		fprintf(stderr, "## Debugger(\"%s\").", label);
654 		fprintf(stderr, " Press Alt-F%ld or Cmd-F%ld to resume.\n", space0 + 1, space0 + 1);
655 
656 		if (IsLocked())
657 			Unlock();
658 
659 		// Switch to debug workspace
660 		_BAppServerLink_ link;
661 		link.fSession->swrite_l(WS_SWITCH_WORKSPACE);
662 		link.fSession->swrite_l(debug_workspace);
663 		link.fSession->sync();
664 
665 		// Suspend ourself
666 		suspend_thread(find_thread(NULL));
667 
668 		Lock();
669 	}
670 }
671 
672 
673 status_t
674 BWindowScreen::Perform(perform_code d,
675 					   void *arg)
676 {
677 	return inherited::Perform(d, arg);
678 }
679 
680 
681 void
682 BWindowScreen::_ReservedWindowScreen1()
683 {
684 }
685 
686 
687 void
688 BWindowScreen::_ReservedWindowScreen2()
689 {
690 }
691 
692 
693 void
694 BWindowScreen::_ReservedWindowScreen3()
695 {
696 }
697 
698 
699 void
700 BWindowScreen::_ReservedWindowScreen4()
701 {
702 }
703 
704 
705 /* unimplemented for protection of the user:
706  *
707  * BWindowScreen::BWindowScreen()
708  * BWindowScreen::BWindowScreen(BWindowScreen &)
709  * BWindowScreen &BWindowScreen::operator=(BWindowScreen &)
710  */
711 
712 
713 BRect
714 BWindowScreen::CalcFrame(int32 index, int32 space, display_mode *dmode)
715 {
716 	BScreen screen;
717 	if (dmode)
718 		screen.GetMode(dmode);
719 
720 	return screen.Frame();
721 }
722 
723 
724 int32
725 BWindowScreen::SetFullscreen(int32 enable)
726 {
727 	a_session->swrite_l(WS_SET_FULLSCREEN);
728 	a_session->swrite_l(server_token);
729 	a_session->swrite_l(enable);
730 	a_session->sync();
731 
732 	int32 result, retval;
733 
734 	a_session->sread(sizeof(result), &result);
735 	a_session->sread(sizeof(retval), &retval);
736 
737 	return retval;
738 }
739 
740 status_t
741 BWindowScreen::InitData(uint32 space, uint32 attributes)
742 {
743 	BScreen screen(this);
744 	debug_state = attributes & B_ENABLE_DEBUGGER;
745 	debug_list_count = 0;
746 	debug_list = 0;
747 	debug_first = true;
748 
749 	debug_sem = create_sem(1, "WindowScreen debug sem");
750 	old_space = (display_mode *)calloc(0x1, sizeof(display_mode));
751 	new_space = (display_mode *)calloc(0x1, sizeof(display_mode));
752 
753 	screen.GetModeList(&mode_list, &mode_count);
754 
755 	_attributes = attributes;
756 
757 	display_mode *n_space = new_space;
758 	screen_index = 0;
759 	lock_state = 0;
760 	addon_state = 0;
761 	direct_enable = 0;
762 	window_state = 0;
763 
764 	space_mode = 1;
765 
766 	GetModeFromSpace(space, n_space);
767 
768 	space0 = 0;
769 
770 	SetWorkspaces(B_CURRENT_WORKSPACE);
771 
772 	SetFullscreen(1);
773 	work_state = 1;
774 	debug_workspace = 0;
775 	const color_map *map = screen.ColorMap();
776 	memcpy(colorList, map->color_list, 256);
777 
778 	GetCardInfo();
779 	activate_sem = create_sem(0, "WindowScreen start lock");
780 	activate_state = 0;
781 
782 
783 	return B_OK;
784 }
785 
786 
787 status_t
788 BWindowScreen::SetActiveState(int32 state)
789 {
790 	status_t status = B_ERROR;
791 	if (state == 1) {
792 		be_app->HideCursor();
793 		if (be_app->IsCursorHidden()
794 			&& (status = SetLockState(1)) == B_OK) {
795 			status = AssertDisplayMode(new_space);
796 			if (status == B_OK) {
797 				if (!activate_state) {
798 					while (acquire_sem(activate_sem) == B_INTERRUPTED)
799 						;
800 				}
801 				SetColorList(colorList);
802 				if (debug_state && !debug_first) {
803 					SuspensionHook(true);
804 					Resume();
805 				} else {
806 					debug_first = true;
807 					ScreenConnected(true);
808 				}
809 				if (status == B_OK)
810 					return status;
811 
812 			} else
813 				SetLockState(0);
814 
815 			be_app->ShowCursor();
816 		}
817 	} else {
818 		if (debug_state && !debug_first) {
819 			Suspend();
820 			SuspensionHook(false);
821 		} else
822 			ScreenConnected(false);
823 
824 		status = SetLockState(0);
825 		if (status == B_OK) {
826 			be_app->ShowCursor();
827 			if (activate_state) {
828 				_BAppServerLink_ link;
829 				link.fSession->swrite_l(0xF27);
830 				link.fSession->swrite_l(screen_index);
831 				link.fSession->swrite_l(0);
832 				link.fSession->swrite_l(255);
833 				const color_map *colorMap = system_colors();
834 				link.fSession->swrite(256 * sizeof(rgb_color), const_cast<rgb_color *>(colorMap->color_list));
835 				link.fSession->sync();
836 			}
837 		}
838 	}
839 	return status;
840 }
841 
842 status_t
843 BWindowScreen::SetLockState(int32 state)
844 {
845 	if(addon_state == 1 && state == 1) {
846 		m_wei();
847 		fill_rect_global = NULL;
848 		blit_rect_global = NULL;
849 		trans_blit_rect_global = NULL;
850 		scaled_filtered_blit_rect_global = NULL;
851 		wait_idle_global = NULL;
852 		et_global = NULL;
853 		acquire_engine_global = NULL;
854 		release_engine_global = NULL;
855 	}
856 
857 	_BAppServerLink_ link;
858 	link.fSession->swrite_l(0x00000efb);
859 	link.fSession->swrite_l(screen_index);
860 	link.fSession->swrite_l(state);
861 	link.fSession->swrite_l(server_token);
862 	link.fSession->sync();
863 
864 	status_t status;
865 	link.fSession->sread(sizeof(status), &status);
866 
867 	if (status == B_NO_ERROR) {
868 		lock_state = state;
869 		if (state == 1) {
870 			if (addon_state == 0) {
871 				status = InitClone();
872 
873 				if (status == B_OK) {
874 					addon_state = 1;
875 					m_wei = (wait_engine_idle)m_gah(B_WAIT_ENGINE_IDLE, NULL);
876 					m_re = (release_engine)m_gah(B_RELEASE_ENGINE, NULL);
877 					m_ae = (acquire_engine)m_gah(B_ACQUIRE_ENGINE, NULL);
878 				} else
879 					addon_state = -1;
880 			}
881 
882 			if (addon_state == 1 && state == 1) {
883 				fill_rect_global = fill_rect;
884 				blit_rect_global = blit_rect;
885 				trans_blit_rect_global = trans_blit_rect;
886 				scaled_filtered_blit_rect_global = scaled_filtered_blit_rect;
887 				wait_idle_global = m_wei;
888 				et_global = et;
889 				acquire_engine_global = m_ae;
890 				release_engine_global = m_re;
891 				m_wei();
892 			}
893 		}
894 	}
895 
896 	return status;
897 }
898 
899 
900 void
901 BWindowScreen::GetCardInfo()
902 {
903 	BScreen screen(this);
904 	frame_buffer_config config;
905 
906 	display_mode mode;
907 	uint32 bits_per_pixel;
908 
909 	card_info.version = 2;
910 	card_info.id = 0;
911 	screen.GetMode(&mode);
912 
913 	switch(mode.space & 0x0fff) {
914 		case B_CMAP8:
915 			bits_per_pixel = 8;
916 			break;
917 		case B_RGB16:
918 			bits_per_pixel = 16;
919 			break;
920 		case B_RGB32:
921 			bits_per_pixel = 32;
922 			break;
923 		default:
924 			bits_per_pixel = 0;
925 			break;
926 	}
927 	card_info.bits_per_pixel = bits_per_pixel;
928 	card_info.width = mode.virtual_width;
929 	card_info.height = mode.virtual_height;
930 
931 	if (mode.space & 0x10)
932 		strncpy(card_info.rgba_order, "rgba", 4);
933 	else
934 		strncpy(card_info.rgba_order, "bgra", 4);
935 
936 	card_info.flags = 0;
937 
938 	if (mode.flags & B_SCROLL)
939 		card_info.flags = B_FRAME_BUFFER_CONTROL;
940 	if (mode.flags & B_PARALLEL_ACCESS)
941 		card_info.flags |= B_PARALLEL_BUFFER_ACCESS;
942 
943 	screen_id id = screen.ID();
944 	_BAppServerLink_ link;
945 	link.fSession->swrite_l(WS_GET_FRAMEBUFFER);
946 	link.fSession->swrite_l(id.id);
947 	link.fSession->sync();
948 
949 	int32 result;
950 	link.fSession->sread(sizeof(result), &result);
951 
952 	if(result == B_NO_ERROR) {
953 		link.fSession->sread(sizeof(frame_buffer_config), &config);
954 		card_info.id = id.id;
955 		card_info.frame_buffer = config.frame_buffer;
956 		card_info.bytes_per_row = config.bytes_per_row;
957 	}
958 	memcpy(&card_info_global, &card_info, sizeof(graphics_card_info));
959 }
960 
961 
962 void
963 BWindowScreen::Suspend()
964 {
965 	CALLED();
966 
967 	while (acquire_sem(debug_sem) == B_INTERRUPTED)
968 		;
969 
970 	// Suspend all the registered threads
971 	for (int i = 0; i < debug_list_count; i++) {
972 		snooze(10000);
973 		suspend_thread(debug_list[i]);
974 	}
975 
976 	graphics_card_info *info = CardInfo();
977 	size_t fbSize = info->bytes_per_row * info->height;
978 
979 	// Save the content of the frame buffer into the local buffer
980 	debug_buffer = (char *)malloc(fbSize);
981 	memcpy(debug_buffer, info->frame_buffer, fbSize);
982 }
983 
984 
985 void
986 BWindowScreen::Resume()
987 {
988 	CALLED();
989 	graphics_card_info *info = CardInfo();
990 
991 	// Copy the content of the debug_buffer back into the frame buffer.
992 	memcpy(info->frame_buffer, debug_buffer, info->bytes_per_row * info->height);
993 	free(debug_buffer);
994 
995 	// Resume all the registered threads
996 	for (int i = 0; i < debug_list_count; i++)
997 		resume_thread(debug_list[i]);
998 
999 	release_sem(debug_sem);
1000 }
1001 
1002 
1003 status_t
1004 BWindowScreen::GetModeFromSpace(uint32 space, display_mode *dmode)
1005 {
1006 	uint32 out_space;
1007 	int32 width, height;
1008 	status_t ret = B_ERROR;
1009 
1010 	mode2parms(space, &out_space, &width, &height);
1011 	// mode2parms converts the space to actual width, height and color_space, e.g B_8_BIT_640x480
1012 
1013 	for (uint32 i = 0; i < mode_count; i++) {
1014 		if (mode_list[i].space == out_space && mode_list[i].virtual_width == width
1015 			&& mode_list[i].virtual_height == height) {
1016 
1017 			memcpy(dmode, &mode_list[i], sizeof(display_mode));
1018 			ret = B_OK;
1019 			break;
1020 		}
1021 	}
1022 
1023 	return ret;
1024 }
1025 
1026 
1027 status_t
1028 BWindowScreen::InitClone()
1029 {
1030 	_BAppServerLink_ link;
1031 	link.fSession->swrite_l(WS_GET_ACCELERANT_NAME);
1032 	link.fSession->swrite_l(screen_index);
1033 	link.fSession->sync();
1034 
1035 	int32 result;
1036 	link.fSession->sread(sizeof(result), &result);
1037 	if (result != B_OK)
1038 		return result;
1039 
1040 	link.fSession->sread(sizeof(result), &result); // read length of accelerant's name
1041 
1042 	char *addonName = (char *)malloc((result + 1) * sizeof (char));
1043 	link.fSession->sread(result, addonName); // read the accelerant's name
1044 	addonName[result] = '\0';
1045 
1046 	link.fSession->swrite_l(WS_GET_DRIVER_NAME); // get driver's name without the /dev/
1047 	link.fSession->swrite_l(screen_index);
1048 	link.fSession->sync();
1049 
1050 	link.fSession->sread(sizeof(result), &result);
1051 	if (result != B_OK)
1052 		return result;
1053 
1054 	link.fSession->sread(sizeof(result), &result);
1055 	// result now contains the length of the buffer needed for the drivers path name
1056 
1057 	char *path = (char *)malloc((result + 1) * sizeof(char));
1058 	link.fSession->sread(result, path);
1059 	path[result] = '\0';
1060 	// path now contains the driver's name
1061 
1062 	// load the accelerant
1063 	addon_image = load_add_on(addonName);
1064 
1065 	free(addonName);
1066 
1067 	if(addon_image < 0)
1068 		return B_ERROR;
1069 
1070 	// now get the symbol for GetAccelerantHook m_gah
1071 	if (get_image_symbol(addon_image, "get_accelerant_hook",
1072 		B_SYMBOL_TYPE_ANY, (void **)&m_gah) < 0)
1073 			return B_ERROR;
1074 
1075 	// now use m_gah to get a pointer to the accelerant's clone accelerant
1076 	clone_accelerant clone = (clone_accelerant)m_gah(B_CLONE_ACCELERANT, 0);
1077 
1078 	if (!clone)
1079 		return B_ERROR;
1080 
1081 	// test if the driver supports cloning of the accelerant, using the path we got earlier
1082 	result = clone((void *)path);
1083 	free(path);
1084 
1085 	if (result != 0) {
1086 		unload_add_on(addon_image);
1087 		addon_image = -1;
1088 	}
1089 
1090 	return result;
1091 }
1092 
1093 
1094 status_t
1095 BWindowScreen::AssertDisplayMode(display_mode *dmode)
1096 {
1097 	status_t result;
1098 	_BAppServerLink_ link;
1099 
1100 	link.fSession->swrite_l(WS_GET_DISPLAY_MODE); // check display_mode valid command
1101 	link.fSession->swrite_l(screen_index);
1102 	link.fSession->swrite(sizeof(display_mode), (void *)dmode);
1103 	link.fSession->sync();
1104 
1105 	link.fSession->sread(sizeof(result), &result);
1106 
1107 	// if the result is B_OK, we copy the dmode to new_space
1108 	if (result == B_OK) {
1109 		memcpy(new_space, dmode, sizeof(display_mode));
1110 		space_mode = 1;
1111 	}
1112 	GetCardInfo();
1113 
1114 	format_info.bits_per_pixel = card_info.bits_per_pixel;
1115 	format_info.bytes_per_row = card_info.bytes_per_row;
1116 	format_info.width = card_info.width;
1117 	format_info.height = card_info.height;
1118 	format_info.display_width = card_info.width;
1119 	format_info.display_height = card_info.height;
1120 	format_info.display_x = 0;
1121 	format_info.display_y = 0;
1122 
1123 	return result;
1124 }
1125