xref: /haiku/src/kits/game/WindowScreen.cpp (revision 17889a8c70dbb3d59c1412f6431968753c767bab)
1 /*
2  * Copyright 2002-2009, Haiku. All Rights Reserved.
3  * Copyright 2002-2005,
4  *		Marcus Overhagen,
5  *		Stefano Ceccherini (stefano.ceccherini@gmail.com),
6  *		Carwyn Jones (turok2@currantbun.com)
7  *		All rights reserved.
8  *
9  * Distributed under the terms of the MIT License.
10  */
11 
12 
13 #include <WindowScreen.h>
14 
15 #include <new>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include <Application.h>
21 #include <Screen.h>
22 #include <String.h>
23 
24 #include <AppServerLink.h>
25 #include <input_globals.h>
26 #include <InputServerTypes.h>
27 #include <InterfacePrivate.h>
28 #include <ServerProtocol.h>
29 #include <WindowPrivate.h>
30 
31 
32 using BPrivate::AppServerLink;
33 
34 
35 //#define TRACE_WINDOWSCREEN 1
36 #if TRACE_WINDOWSCREEN
37 #	define CALLED() printf("%s\n", __PRETTY_FUNCTION__);
38 #else
39 #	define CALLED() ;
40 #endif
41 
42 
43 // Acceleration hooks pointers
44 static fill_rectangle sFillRectHook;
45 static screen_to_screen_blit sBlitRectHook;
46 static screen_to_screen_transparent_blit sTransparentBlitHook;
47 static screen_to_screen_scaled_filtered_blit sScaledFilteredBlitHook;
48 static wait_engine_idle sWaitIdleHook;
49 static acquire_engine sAcquireEngineHook;
50 static release_engine sReleaseEngineHook;
51 
52 static engine_token *sEngineToken;
53 
54 
55 // Helper methods which translates the pre r5 graphics methods to r5 ones
56 static int32
57 card_sync()
58 {
59 	sWaitIdleHook();
60 	return 0;
61 }
62 
63 
64 static int32
65 blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width, int32 height)
66 {
67 	blit_params param;
68 	param.src_left = sx;
69 	param.src_top = sy;
70 	param.dest_left = dx;
71 	param.dest_top = dy;
72 	param.width = width;
73 	param.height = height;
74 
75 	sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
76 	sBlitRectHook(sEngineToken, &param, 1);
77 	sReleaseEngineHook(sEngineToken, NULL);
78 	return 0;
79 }
80 
81 
82 // TODO: This function seems not to be exported through CardHookAt().
83 // At least, nothing I've tried uses it.
84 #if 0
85 static int32
86 transparent_blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width,
87 	int32 height, uint32 transparent_color)
88 {
89 	blit_params param;
90 	param.src_left = sx;
91 	param.src_top = sy;
92 	param.dest_left = dx;
93 	param.dest_top = dy;
94 	param.width = width;
95 	param.height = height;
96 
97 	sAcquireEngineHook(B_2D_ACCELERATION, 0xff, 0, &sEngineToken);
98 	sTransparentBlitHook(sEngineToken, transparent_color, &param, 1);
99 	sReleaseEngineHook(sEngineToken, 0);
100 	return 0;
101 }
102 #endif
103 
104 
105 static int32
106 scaled_filtered_blit(int32 sx, int32 sy, int32 sw, int32 sh, int32 dx, int32 dy,
107 	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 	sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
120 	sScaledFilteredBlitHook(sEngineToken, &param, 1);
121 	sReleaseEngineHook(sEngineToken, NULL);
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 	sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
136 	sFillRectHook(sEngineToken, color_index, &param, 1);
137 	sReleaseEngineHook(sEngineToken, NULL);
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 	sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
152 	sFillRectHook(sEngineToken, color, &param, 1);
153 	sReleaseEngineHook(sEngineToken, NULL);
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 	sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
168 	sFillRectHook(sEngineToken, color, &param, 1);
169 	sReleaseEngineHook(sEngineToken, NULL);
170 	return 0;
171 }
172 
173 
174 //	#pragma mark - public API calls
175 
176 
177 void
178 set_mouse_position(int32 x, int32 y)
179 {
180 	BMessage command(IS_SET_MOUSE_POSITION);
181 	BMessage reply;
182 
183 	command.AddPoint("where", BPoint(x, y));
184 	_control_input_server_(&command, &reply);
185 }
186 
187 
188 //	#pragma mark -
189 
190 
191 BWindowScreen::BWindowScreen(const char *title, uint32 space, status_t *error,
192 		bool debugEnable)
193 	:
194 	BWindow(BScreen().Frame(), title, B_NO_BORDER_WINDOW_LOOK,
195 		kWindowScreenFeel, kWindowScreenFlag | B_NOT_MINIMIZABLE
196 			| B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE,
197 		B_CURRENT_WORKSPACE)
198 {
199 	CALLED();
200 	uint32 attributes = 0;
201 	if (debugEnable)
202 		attributes |= B_ENABLE_DEBUGGER;
203 
204 	status_t status = _InitData(space, attributes);
205 	if (error)
206 		*error = status;
207 }
208 
209 
210 BWindowScreen::BWindowScreen(const char *title, uint32 space,
211 		uint32 attributes, status_t *error)
212 	:
213 	BWindow(BScreen().Frame(), title, B_NO_BORDER_WINDOW_LOOK,
214 		kWindowScreenFeel, kWindowScreenFlag | B_NOT_MINIMIZABLE
215 			| B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE,
216 		B_CURRENT_WORKSPACE)
217 {
218 	CALLED();
219 	status_t status = _InitData(space, attributes);
220 	if (error)
221 		*error = status;
222 }
223 
224 
225 BWindowScreen::~BWindowScreen()
226 {
227 	CALLED();
228 	_DisposeData();
229 }
230 
231 
232 void
233 BWindowScreen::Quit(void)
234 {
235 	CALLED();
236 	Disconnect();
237 	BWindow::Quit();
238 }
239 
240 
241 void
242 BWindowScreen::ScreenConnected(bool active)
243 {
244 	// Implemented in subclasses
245 }
246 
247 
248 void
249 BWindowScreen::Disconnect()
250 {
251 	CALLED();
252 	if (fLockState == 1) {
253 		if (fDebugState)
254 			fDebugFirst = true;
255 		_Deactivate();
256 	}
257 
258 	be_app->ShowCursor();
259 }
260 
261 
262 void
263 BWindowScreen::WindowActivated(bool active)
264 {
265 	CALLED();
266 	fWindowState = active;
267 	if (active && fLockState == 0 && fWorkState)
268 		_Activate();
269 }
270 
271 
272 void
273 BWindowScreen::WorkspaceActivated(int32 workspace, bool state)
274 {
275 	CALLED();
276 	fWorkState = state;
277 
278 	if (state) {
279 		if (fLockState == 0 && fWindowState) {
280 			_Activate();
281 			if (!IsHidden()) {
282 				Activate(true);
283 				WindowActivated(true);
284 			}
285 		}
286 	} else if (fLockState)
287 		_Deactivate();
288 }
289 
290 
291 void
292 BWindowScreen::ScreenChanged(BRect screenFrame, color_space depth)
293 {
294 	// Implemented in subclasses
295 }
296 
297 
298 void
299 BWindowScreen::Hide()
300 {
301 	CALLED();
302 
303 	Disconnect();
304 	BWindow::Hide();
305 }
306 
307 
308 void
309 BWindowScreen::Show()
310 {
311 	CALLED();
312 
313 	BWindow::Show();
314 }
315 
316 
317 void
318 BWindowScreen::SetColorList(rgb_color *list, int32 firstIndex, int32 lastIndex)
319 {
320 	CALLED();
321 	if (firstIndex < 0 || lastIndex > 255 || firstIndex > lastIndex)
322 		return;
323 
324 	if (!Lock())
325 		return;
326 
327 	if (!fActivateState) {
328 		// If we aren't active, we just change our local palette
329 		for (int32 x = firstIndex; x <= lastIndex; x++) {
330 			fPalette[x] = list[x - firstIndex];
331 		}
332 	} else {
333 		uint8 colors[3 * 256];
334 			// the color table has 3 bytes per color
335 		int32 j = 0;
336 
337 		for (int32 x = firstIndex; x <= lastIndex; x++) {
338 			fPalette[x] = list[x - firstIndex];
339 				// update our local palette as well
340 
341 			colors[j++] = fPalette[x].red;
342 			colors[j++] = fPalette[x].green;
343 			colors[j++] = fPalette[x].blue;
344 		}
345 
346 		if (fAddonImage >= 0) {
347 			set_indexed_colors setIndexedColors
348 				= (set_indexed_colors)fGetAccelerantHook(B_SET_INDEXED_COLORS,
349 					NULL);
350 			if (setIndexedColors != NULL) {
351 				setIndexedColors(255, 0,
352 					colors, 0);
353 			}
354 		}
355 
356 		// TODO: Tell the app_server about our changes
357 
358 		BScreen screen(this);
359 		screen.WaitForRetrace();
360 	}
361 
362 	Unlock();
363 }
364 
365 
366 status_t
367 BWindowScreen::SetSpace(uint32 space)
368 {
369 	CALLED();
370 
371 	display_mode mode;
372 	status_t status = _GetModeFromSpace(space, &mode);
373 	if (status == B_OK)
374 		status = _AssertDisplayMode(&mode);
375 
376 	return status;
377 }
378 
379 
380 bool
381 BWindowScreen::CanControlFrameBuffer()
382 {
383 	return (fCardInfo.flags & B_FRAME_BUFFER_CONTROL) != 0;
384 }
385 
386 
387 status_t
388 BWindowScreen::SetFrameBuffer(int32 width, int32 height)
389 {
390 	CALLED();
391 	display_mode highMode = *fDisplayMode;
392 	highMode.flags |= B_SCROLL;
393 
394 	highMode.virtual_height = (int16)height;
395 	highMode.virtual_width = (int16)width;
396 
397 	display_mode lowMode = highMode;
398 	display_mode mode = highMode;
399 
400 	BScreen screen(this);
401 	status_t status = screen.ProposeMode(&mode, &lowMode, &highMode);
402 	if (status == B_OK)
403 		status = _AssertDisplayMode(&mode);
404 
405 	return status;
406 }
407 
408 
409 status_t
410 BWindowScreen::MoveDisplayArea(int32 x, int32 y)
411 {
412 	CALLED();
413 	move_display_area moveDisplayArea
414 		= (move_display_area)fGetAccelerantHook(B_MOVE_DISPLAY, NULL);
415 	if (moveDisplayArea && moveDisplayArea((int16)x, (int16)y) == B_OK) {
416 		fFrameBufferInfo.display_x = x;
417 		fFrameBufferInfo.display_y = y;
418 		fDisplayMode->h_display_start = x;
419 		fDisplayMode->v_display_start = y;
420 		return B_OK;
421 	}
422 	return B_ERROR;
423 }
424 
425 
426 #if 0
427 void *
428 BWindowScreen::IOBase()
429 {
430 	// Not supported
431 	return NULL;
432 }
433 #endif
434 
435 
436 rgb_color *
437 BWindowScreen::ColorList()
438 {
439 	CALLED();
440 	return fPalette;
441 }
442 
443 
444 frame_buffer_info *
445 BWindowScreen::FrameBufferInfo()
446 {
447 	CALLED();
448 	return &fFrameBufferInfo;
449 }
450 
451 
452 graphics_card_hook
453 BWindowScreen::CardHookAt(int32 index)
454 {
455 	CALLED();
456 	if (fAddonImage < 0)
457 		return NULL;
458 
459 	graphics_card_hook hook = NULL;
460 
461 	switch (index) {
462 		case 5: // 8 bit fill rect
463 			if (sFillRectHook)
464 				hook = (graphics_card_hook)draw_rect_8;
465 			break;
466 		case 6: // 32 bit fill rect
467 			if (sFillRectHook)
468 				hook = (graphics_card_hook)draw_rect_32;
469 			break;
470 		case 7: // screen to screen blit
471 			if (sBlitRectHook)
472 				hook = (graphics_card_hook)blit;
473 			break;
474 		case 8: // screen to screen scaled filtered blit
475 			if (sScaledFilteredBlitHook)
476 				hook = (graphics_card_hook)scaled_filtered_blit;
477 			break;
478 		case 10: // sync aka wait for graphics card idle
479 			if (sWaitIdleHook)
480 				hook = (graphics_card_hook)card_sync;
481 			break;
482 		case 13: // 16 bit fill rect
483 			if (sFillRectHook)
484 				hook = (graphics_card_hook)draw_rect_16;
485 			break;
486 		default:
487 			break;
488 	}
489 
490 	return hook;
491 }
492 
493 
494 graphics_card_info *
495 BWindowScreen::CardInfo()
496 {
497 	CALLED();
498 	return &fCardInfo;
499 }
500 
501 
502 void
503 BWindowScreen::RegisterThread(thread_id thread)
504 {
505 	CALLED();
506 
507 	status_t status;
508 	do {
509 		status = acquire_sem(fDebugSem);
510 	} while (status == B_INTERRUPTED);
511 
512 	if (status < B_OK)
513 		return;
514 
515 	void *newDebugList = realloc(fDebugThreads,
516 		(fDebugThreadCount + 1) * sizeof(thread_id));
517 	if (newDebugList != NULL) {
518 		fDebugThreads = (thread_id *)newDebugList;
519 		fDebugThreads[fDebugThreadCount] = thread;
520 		fDebugThreadCount++;
521 	}
522 	release_sem(fDebugSem);
523 }
524 
525 
526 void
527 BWindowScreen::SuspensionHook(bool active)
528 {
529 	// Implemented in subclasses
530 }
531 
532 
533 void
534 BWindowScreen::Suspend(char* label)
535 {
536 	CALLED();
537 	if (fDebugState) {
538 		fprintf(stderr, "## Debugger(\"%s\").", label);
539 		fprintf(stderr, " Press Alt-F%" B_PRId32 " or Cmd-F%" B_PRId32 " to resume.\n",
540 			fWorkspaceIndex + 1, fWorkspaceIndex + 1);
541 
542 		if (IsLocked())
543 			Unlock();
544 
545 		activate_workspace(fDebugWorkspace);
546 
547 		// Suspend ourself
548 		suspend_thread(find_thread(NULL));
549 
550 		Lock();
551 	}
552 }
553 
554 
555 status_t
556 BWindowScreen::Perform(perform_code d, void* arg)
557 {
558 	return inherited::Perform(d, arg);
559 }
560 
561 
562 // Reserved for future binary compatibility
563 void BWindowScreen::_ReservedWindowScreen1() {}
564 void BWindowScreen::_ReservedWindowScreen2() {}
565 void BWindowScreen::_ReservedWindowScreen3() {}
566 void BWindowScreen::_ReservedWindowScreen4() {}
567 
568 
569 status_t
570 BWindowScreen::_InitData(uint32 space, uint32 attributes)
571 {
572 	CALLED();
573 
574 	fDebugState = attributes & B_ENABLE_DEBUGGER;
575 	fDebugThreadCount = 0;
576 	fDebugThreads = NULL;
577 	fDebugFirst = true;
578 
579 	fAttributes = attributes;
580 		// TODO: not really used right now, but should probably be known by
581 		// the app_server
582 
583 	fWorkspaceIndex = fDebugWorkspace = current_workspace();
584 	fLockState = 0;
585 	fAddonImage = -1;
586 	fWindowState = 0;
587 	fOriginalDisplayMode = NULL;
588 	fDisplayMode = NULL;
589 	fModeList = NULL;
590 	fModeCount = 0;
591 	fDebugSem = -1;
592 	fActivateState = false;
593 	fWorkState = false;
594 
595 	status_t status = B_ERROR;
596 	try {
597 		fOriginalDisplayMode = new display_mode;
598 		fDisplayMode = new display_mode;
599 
600 		BScreen screen(this);
601 		status = screen.GetMode(fOriginalDisplayMode);
602 		if (status < B_OK)
603 			throw status;
604 
605 		status = screen.GetModeList(&fModeList, &fModeCount);
606 		if (status < B_OK)
607 			throw status;
608 
609 		status = _GetModeFromSpace(space, fDisplayMode);
610 		if (status < B_OK)
611 			throw status;
612 
613 		status = _GetCardInfo();
614 		if (status < B_OK)
615 			throw status;
616 
617 		fDebugSem = create_sem(1, "WindowScreen debug sem");
618 		if (fDebugSem < B_OK)
619 			throw (status_t)fDebugSem;
620 
621 		memcpy((void*)fPalette, screen.ColorMap()->color_list, sizeof(fPalette));
622 		fActivateState = false;
623 		fWorkState = true;
624 
625 		status = B_OK;
626 	} catch (std::bad_alloc&) {
627 		status = B_NO_MEMORY;
628 	} catch (status_t error) {
629 		status = error;
630 	} catch (...) {
631 		status = B_ERROR;
632 	}
633 
634 	if (status != B_OK)
635 		_DisposeData();
636 
637 	return status;
638 }
639 
640 
641 void
642 BWindowScreen::_DisposeData()
643 {
644 	CALLED();
645 	Disconnect();
646 	if (fAddonImage >= 0) {
647 		unload_add_on(fAddonImage);
648 		fAddonImage = -1;
649 	}
650 
651 	delete_sem(fDebugSem);
652 	fDebugSem = -1;
653 
654 	if (fDebugState)
655 		activate_workspace(fDebugWorkspace);
656 
657 	delete fDisplayMode;
658 	fDisplayMode = NULL;
659 	delete fOriginalDisplayMode;
660 	fOriginalDisplayMode = NULL;
661 	free(fModeList);
662 	fModeList = NULL;
663 	fModeCount = 0;
664 
665 	fLockState = 0;
666 }
667 
668 
669 status_t
670 BWindowScreen::_LockScreen(bool lock)
671 {
672 	if (fActivateState == lock)
673 		return B_OK;
674 
675 	// TODO: the BWindowScreen should use the same mechanism as BDirectWindows!
676 	BPrivate::AppServerLink link;
677 
678 	link.StartMessage(AS_DIRECT_SCREEN_LOCK);
679 	link.Attach<bool>(lock);
680 
681 	status_t status = B_ERROR;
682 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
683 		fActivateState = lock;
684 
685 	return status;
686 }
687 
688 
689 status_t
690 BWindowScreen::_Activate()
691 {
692 	CALLED();
693 	status_t status = _AssertDisplayMode(fDisplayMode);
694 	if (status < B_OK)
695 		return status;
696 
697 	status = _SetupAccelerantHooks();
698 	if (status < B_OK)
699 		return status;
700 
701 	if (!fActivateState) {
702 		status = _LockScreen(true);
703 		if (status != B_OK)
704 			return status;
705 	}
706 
707 	be_app->HideCursor();
708 
709 	SetColorList(fPalette);
710 	if (fDebugState && !fDebugFirst) {
711 		SuspensionHook(true);
712 		_Resume();
713 	} else {
714 		fDebugFirst = true;
715 		ScreenConnected(true);
716 	}
717 
718 	return B_OK;
719 }
720 
721 
722 status_t
723 BWindowScreen::_Deactivate()
724 {
725 	CALLED();
726 
727 	if (fDebugState && !fDebugFirst) {
728 		_Suspend();
729 		SuspensionHook(false);
730 	} else
731 		ScreenConnected(false);
732 
733 	if (fActivateState) {
734 		status_t status = _LockScreen(false);
735 		if (status != B_OK)
736 			return status;
737 
738 		BScreen screen(this);
739 		SetColorList((rgb_color *)screen.ColorMap()->color_list);
740 	}
741 
742 	_AssertDisplayMode(fOriginalDisplayMode);
743 	_ResetAccelerantHooks();
744 
745 	be_app->ShowCursor();
746 
747 	return B_OK;
748 }
749 
750 
751 status_t
752 BWindowScreen::_SetupAccelerantHooks()
753 {
754 	CALLED();
755 
756 	status_t status = B_OK;
757 	if (fAddonImage < 0)
758 		status = _InitClone();
759 	else
760 		_ResetAccelerantHooks();
761 
762 	if (status == B_OK) {
763 		sWaitIdleHook = fWaitEngineIdle = (wait_engine_idle)
764 			fGetAccelerantHook(B_WAIT_ENGINE_IDLE, NULL);
765 		sReleaseEngineHook
766 			= (release_engine)fGetAccelerantHook(B_RELEASE_ENGINE, NULL);
767 		sAcquireEngineHook
768 			= (acquire_engine)fGetAccelerantHook(B_ACQUIRE_ENGINE, NULL);
769 		sFillRectHook
770 			= (fill_rectangle)fGetAccelerantHook(B_FILL_RECTANGLE, NULL);
771 		sBlitRectHook = (screen_to_screen_blit)
772 			fGetAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, NULL);
773 		sTransparentBlitHook = (screen_to_screen_transparent_blit)
774 			fGetAccelerantHook(B_SCREEN_TO_SCREEN_TRANSPARENT_BLIT, NULL);
775 		sScaledFilteredBlitHook = (screen_to_screen_scaled_filtered_blit)
776 			fGetAccelerantHook(B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT, NULL);
777 
778 		if (fWaitEngineIdle)
779 			fWaitEngineIdle();
780 
781 		fLockState = 1;
782 	}
783 
784 	return status;
785 }
786 
787 
788 void
789 BWindowScreen::_ResetAccelerantHooks()
790 {
791 	CALLED();
792 	if (fWaitEngineIdle)
793 		fWaitEngineIdle();
794 
795 	sFillRectHook = NULL;
796 	sBlitRectHook = NULL;
797 	sTransparentBlitHook = NULL;
798 	sScaledFilteredBlitHook = NULL;
799 	sWaitIdleHook = NULL;
800 	sEngineToken = NULL;
801 	sAcquireEngineHook = NULL;
802 	sReleaseEngineHook = NULL;
803 
804 	fWaitEngineIdle = NULL;
805 
806 	fLockState = 0;
807 }
808 
809 
810 status_t
811 BWindowScreen::_GetCardInfo()
812 {
813 	CALLED();
814 
815 	BScreen screen(this);
816 	display_mode mode;
817 	status_t status = screen.GetMode(&mode);
818 	if (status < B_OK)
819 		return status;
820 
821 	uint32 bitsPerPixel;
822 	switch(mode.space & 0x0fff) {
823 		case B_CMAP8:
824 			bitsPerPixel = 8;
825 			break;
826 		case B_RGB15:
827 			bitsPerPixel = 15;
828 			break;
829 		case B_RGB16:
830 			bitsPerPixel = 16;
831 			break;
832 		case B_RGB32:
833 			bitsPerPixel = 32;
834 			break;
835 		default:
836 			bitsPerPixel = 0;
837 			break;
838 	}
839 
840 	fCardInfo.version = 2;
841 	fCardInfo.id = screen.ID().id;
842 	fCardInfo.bits_per_pixel = bitsPerPixel;
843 	fCardInfo.width = mode.virtual_width;
844 	fCardInfo.height = mode.virtual_height;
845 
846 	if (mode.space & 0x10)
847 		memcpy(fCardInfo.rgba_order, "rgba", 4);
848 	else
849 		memcpy(fCardInfo.rgba_order, "bgra", 4);
850 
851 	fCardInfo.flags = 0;
852 	if (mode.flags & B_SCROLL)
853 		fCardInfo.flags |= B_FRAME_BUFFER_CONTROL;
854 	if (mode.flags & B_PARALLEL_ACCESS)
855 		fCardInfo.flags |= B_PARALLEL_BUFFER_ACCESS;
856 
857 	AppServerLink link;
858 	link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG);
859 	link.Attach<screen_id>(screen.ID());
860 
861 	status_t result = B_ERROR;
862 	if (link.FlushWithReply(result) < B_OK || result < B_OK)
863 		return result;
864 
865 	frame_buffer_config config;
866 	link.Read<frame_buffer_config>(&config);
867 
868 	fCardInfo.frame_buffer = config.frame_buffer;
869 	fCardInfo.bytes_per_row = config.bytes_per_row;
870 
871 	return B_OK;
872 }
873 
874 
875 void
876 BWindowScreen::_Suspend()
877 {
878 	CALLED();
879 
880 	status_t status;
881 	do {
882 		status = acquire_sem(fDebugSem);
883 	} while (status == B_INTERRUPTED);
884 
885 	if (status != B_OK)
886 		return;
887 
888 	// Suspend all the registered threads
889 	for (int32 i = 0; i < fDebugThreadCount; i++) {
890 		snooze(10000);
891 		suspend_thread(fDebugThreads[i]);
892 	}
893 
894 	graphics_card_info *info = CardInfo();
895 	size_t fbSize = info->bytes_per_row * info->height;
896 
897 	// Save the content of the frame buffer into the local buffer
898 	fDebugFrameBuffer = (char *)malloc(fbSize);
899 	memcpy(fDebugFrameBuffer, info->frame_buffer, fbSize);
900 }
901 
902 
903 void
904 BWindowScreen::_Resume()
905 {
906 	CALLED();
907 	graphics_card_info *info = CardInfo();
908 
909 	// Copy the content of the debug_buffer back into the frame buffer.
910 	memcpy(info->frame_buffer, fDebugFrameBuffer,
911 		info->bytes_per_row * info->height);
912 	free(fDebugFrameBuffer);
913 	fDebugFrameBuffer = NULL;
914 
915 	// Resume all the registered threads
916 	for (int32 i = 0; i < fDebugThreadCount; i++) {
917 		resume_thread(fDebugThreads[i]);
918 	}
919 
920 	release_sem(fDebugSem);
921 }
922 
923 
924 status_t
925 BWindowScreen::_GetModeFromSpace(uint32 space, display_mode *dmode)
926 {
927 	CALLED();
928 
929 	int32 width, height;
930 	uint32 colorSpace;
931 	if (!BPrivate::get_mode_parameter(space, width, height, colorSpace))
932 		return B_BAD_VALUE;
933 
934 	for (uint32 i = 0; i < fModeCount; i++) {
935 		if (fModeList[i].space == colorSpace
936 			&& fModeList[i].virtual_width == width
937 			&& fModeList[i].virtual_height == height) {
938 			memcpy(dmode, &fModeList[i], sizeof(display_mode));
939 			return B_OK;
940 		}
941 	}
942 
943 	return B_ERROR;
944 }
945 
946 
947 status_t
948 BWindowScreen::_InitClone()
949 {
950 	CALLED();
951 
952 	if (fAddonImage >= 0)
953 		return B_OK;
954 
955 	BScreen screen(this);
956 
957 	AppServerLink link;
958 	link.StartMessage(AS_GET_ACCELERANT_PATH);
959 	link.Attach<screen_id>(screen.ID());
960 
961 	status_t status = B_ERROR;
962 	if (link.FlushWithReply(status) < B_OK || status < B_OK)
963 		return status;
964 
965 	BString accelerantPath;
966 	link.ReadString(accelerantPath);
967 
968 	link.StartMessage(AS_GET_DRIVER_PATH);
969 	link.Attach<screen_id>(screen.ID());
970 
971 	status = B_ERROR;
972 	if (link.FlushWithReply(status) < B_OK || status < B_OK)
973 		return status;
974 
975 	BString driverPath;
976 	link.ReadString(driverPath);
977 
978 	fAddonImage = load_add_on(accelerantPath.String());
979 	if (fAddonImage < B_OK) {
980 		fprintf(stderr, "InitClone: cannot load accelerant image\n");
981 		return fAddonImage;
982 	}
983 
984 	status = get_image_symbol(fAddonImage, B_ACCELERANT_ENTRY_POINT,
985 		B_SYMBOL_TYPE_TEXT, (void**)&fGetAccelerantHook);
986 	if (status < B_OK) {
987 		fprintf(stderr, "InitClone: cannot get accelerant entry point\n");
988 		unload_add_on(fAddonImage);
989 		fAddonImage = -1;
990 		return B_NOT_SUPPORTED;
991 	}
992 
993 	clone_accelerant cloneHook
994 		= (clone_accelerant)fGetAccelerantHook(B_CLONE_ACCELERANT, NULL);
995 	if (cloneHook == NULL) {
996 		fprintf(stderr, "InitClone: cannot get clone hook\n");
997 		unload_add_on(fAddonImage);
998 		fAddonImage = -1;
999 		return B_NOT_SUPPORTED;
1000 	}
1001 
1002 	status = cloneHook((void*)driverPath.String());
1003 	if (status < B_OK) {
1004 		fprintf(stderr, "InitClone: cannot clone accelerant\n");
1005 		unload_add_on(fAddonImage);
1006 		fAddonImage = -1;
1007 	}
1008 
1009 	return status;
1010 }
1011 
1012 
1013 status_t
1014 BWindowScreen::_AssertDisplayMode(display_mode* displayMode)
1015 {
1016 	CALLED();
1017 
1018 	BScreen screen(this);
1019 
1020 	display_mode currentMode;
1021 	status_t status = screen.GetMode(&currentMode);
1022 	if (status != B_OK)
1023 		return status;
1024 
1025 	if (currentMode.virtual_height != displayMode->virtual_height
1026 		|| currentMode.virtual_width != displayMode->virtual_width
1027 		|| currentMode.space != displayMode->space
1028 		|| currentMode.flags != displayMode->flags) {
1029 		status = screen.SetMode(displayMode);
1030 		if (status != B_OK) {
1031 			fprintf(stderr, "AssertDisplayMode: Setting mode failed: %s\n",
1032 				strerror(status));
1033 			return status;
1034 		}
1035 
1036 		memcpy(fDisplayMode, displayMode, sizeof(display_mode));
1037 	}
1038 
1039 	status = _GetCardInfo();
1040 	if (status != B_OK)
1041 		return status;
1042 
1043 	fFrameBufferInfo.bits_per_pixel = fCardInfo.bits_per_pixel;
1044 	fFrameBufferInfo.bytes_per_row = fCardInfo.bytes_per_row;
1045 	fFrameBufferInfo.width = fCardInfo.width;
1046 	fFrameBufferInfo.height = fCardInfo.height;
1047 	fFrameBufferInfo.display_width = fCardInfo.width;
1048 	fFrameBufferInfo.display_height = fCardInfo.height;
1049 	fFrameBufferInfo.display_x = 0;
1050 	fFrameBufferInfo.display_y = 0;
1051 
1052 	return B_OK;
1053 }
1054