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
32using 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
44static fill_rectangle sFillRectHook;
45static screen_to_screen_blit sBlitRectHook;
46static screen_to_screen_transparent_blit sTransparentBlitHook;
47static screen_to_screen_scaled_filtered_blit sScaledFilteredBlitHook;
48static wait_engine_idle sWaitIdleHook;
49static acquire_engine sAcquireEngineHook;
50static release_engine sReleaseEngineHook;
51
52static engine_token *sEngineToken;
53
54
55// Helper methods which translates the pre r5 graphics methods to r5 ones
56static int32
57card_sync()
58{
59	sWaitIdleHook();
60	return 0;
61}
62
63
64static int32
65blit(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
85static int32
86transparent_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
105static int32
106scaled_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
126static int32
127draw_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
142static int32
143draw_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
158static int32
159draw_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
177void
178set_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
191BWindowScreen::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
210BWindowScreen::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
225BWindowScreen::~BWindowScreen()
226{
227	CALLED();
228	_DisposeData();
229}
230
231
232void
233BWindowScreen::Quit(void)
234{
235	CALLED();
236	Disconnect();
237	BWindow::Quit();
238}
239
240
241void
242BWindowScreen::ScreenConnected(bool active)
243{
244	// Implemented in subclasses
245}
246
247
248void
249BWindowScreen::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
262void
263BWindowScreen::WindowActivated(bool active)
264{
265	CALLED();
266	fWindowState = active;
267	if (active && fLockState == 0 && fWorkState)
268		_Activate();
269}
270
271
272void
273BWindowScreen::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
291void
292BWindowScreen::ScreenChanged(BRect screenFrame, color_space depth)
293{
294	// Implemented in subclasses
295}
296
297
298void
299BWindowScreen::Hide()
300{
301	CALLED();
302
303	Disconnect();
304	BWindow::Hide();
305}
306
307
308void
309BWindowScreen::Show()
310{
311	CALLED();
312
313	BWindow::Show();
314}
315
316
317void
318BWindowScreen::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
366status_t
367BWindowScreen::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
380bool
381BWindowScreen::CanControlFrameBuffer()
382{
383	return (fCardInfo.flags & B_FRAME_BUFFER_CONTROL) != 0;
384}
385
386
387status_t
388BWindowScreen::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
409status_t
410BWindowScreen::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
427void *
428BWindowScreen::IOBase()
429{
430	// Not supported
431	return NULL;
432}
433#endif
434
435
436rgb_color *
437BWindowScreen::ColorList()
438{
439	CALLED();
440	return fPalette;
441}
442
443
444frame_buffer_info *
445BWindowScreen::FrameBufferInfo()
446{
447	CALLED();
448	return &fFrameBufferInfo;
449}
450
451
452graphics_card_hook
453BWindowScreen::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
494graphics_card_info *
495BWindowScreen::CardInfo()
496{
497	CALLED();
498	return &fCardInfo;
499}
500
501
502void
503BWindowScreen::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
526void
527BWindowScreen::SuspensionHook(bool active)
528{
529	// Implemented in subclasses
530}
531
532
533void
534BWindowScreen::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
555status_t
556BWindowScreen::Perform(perform_code d, void* arg)
557{
558	return inherited::Perform(d, arg);
559}
560
561
562// Reserved for future binary compatibility
563void BWindowScreen::_ReservedWindowScreen1() {}
564void BWindowScreen::_ReservedWindowScreen2() {}
565void BWindowScreen::_ReservedWindowScreen3() {}
566void BWindowScreen::_ReservedWindowScreen4() {}
567
568
569status_t
570BWindowScreen::_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(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
641void
642BWindowScreen::_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
669status_t
670BWindowScreen::_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
689status_t
690BWindowScreen::_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
722status_t
723BWindowScreen::_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
751status_t
752BWindowScreen::_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
788void
789BWindowScreen::_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
810status_t
811BWindowScreen::_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
875void
876BWindowScreen::_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
903void
904BWindowScreen::_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
924status_t
925BWindowScreen::_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
947status_t
948BWindowScreen::_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
1013status_t
1014BWindowScreen::_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