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