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