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
card_sync()57 card_sync()
58 {
59 sWaitIdleHook();
60 return 0;
61 }
62
63
64 static int32
blit(int32 sx,int32 sy,int32 dx,int32 dy,int32 width,int32 height)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, ¶m, 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, ¶m, 1);
99 sReleaseEngineHook(sEngineToken, 0);
100 return 0;
101 }
102 #endif
103
104
105 static int32
scaled_filtered_blit(int32 sx,int32 sy,int32 sw,int32 sh,int32 dx,int32 dy,int32 dw,int32 dh)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, ¶m, 1);
121 sReleaseEngineHook(sEngineToken, NULL);
122 return 0;
123 }
124
125
126 static int32
draw_rect_8(int32 sx,int32 sy,int32 sw,int32 sh,uint8 color_index)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, ¶m, 1);
137 sReleaseEngineHook(sEngineToken, NULL);
138 return 0;
139 }
140
141
142 static int32
draw_rect_16(int32 sx,int32 sy,int32 sw,int32 sh,uint16 color)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, ¶m, 1);
153 sReleaseEngineHook(sEngineToken, NULL);
154 return 0;
155 }
156
157
158 static int32
draw_rect_32(int32 sx,int32 sy,int32 sw,int32 sh,uint32 color)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, ¶m, 1);
169 sReleaseEngineHook(sEngineToken, NULL);
170 return 0;
171 }
172
173
174 // #pragma mark - public API calls
175
176
177 void
set_mouse_position(int32 x,int32 y)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
BWindowScreen(const char * title,uint32 space,status_t * error,bool debugEnable)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
BWindowScreen(const char * title,uint32 space,uint32 attributes,status_t * error)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
~BWindowScreen()225 BWindowScreen::~BWindowScreen()
226 {
227 CALLED();
228 _DisposeData();
229 }
230
231
232 void
Quit(void)233 BWindowScreen::Quit(void)
234 {
235 CALLED();
236 Disconnect();
237 BWindow::Quit();
238 }
239
240
241 void
ScreenConnected(bool active)242 BWindowScreen::ScreenConnected(bool active)
243 {
244 // Implemented in subclasses
245 }
246
247
248 void
Disconnect()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
WindowActivated(bool active)263 BWindowScreen::WindowActivated(bool active)
264 {
265 CALLED();
266 fWindowState = active;
267 if (active && fLockState == 0 && fWorkState)
268 _Activate();
269 }
270
271
272 void
WorkspaceActivated(int32 workspace,bool state)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
ScreenChanged(BRect screenFrame,color_space depth)292 BWindowScreen::ScreenChanged(BRect screenFrame, color_space depth)
293 {
294 // Implemented in subclasses
295 }
296
297
298 void
Hide()299 BWindowScreen::Hide()
300 {
301 CALLED();
302
303 Disconnect();
304 BWindow::Hide();
305 }
306
307
308 void
Show()309 BWindowScreen::Show()
310 {
311 CALLED();
312
313 BWindow::Show();
314 }
315
316
317 void
SetColorList(rgb_color * list,int32 firstIndex,int32 lastIndex)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
SetSpace(uint32 space)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
CanControlFrameBuffer()381 BWindowScreen::CanControlFrameBuffer()
382 {
383 return (fCardInfo.flags & B_FRAME_BUFFER_CONTROL) != 0;
384 }
385
386
387 status_t
SetFrameBuffer(int32 width,int32 height)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
MoveDisplayArea(int32 x,int32 y)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 *
ColorList()437 BWindowScreen::ColorList()
438 {
439 CALLED();
440 return fPalette;
441 }
442
443
444 frame_buffer_info *
FrameBufferInfo()445 BWindowScreen::FrameBufferInfo()
446 {
447 CALLED();
448 return &fFrameBufferInfo;
449 }
450
451
452 graphics_card_hook
CardHookAt(int32 index)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 *
CardInfo()495 BWindowScreen::CardInfo()
496 {
497 CALLED();
498 return &fCardInfo;
499 }
500
501
502 void
RegisterThread(thread_id thread)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
SuspensionHook(bool active)527 BWindowScreen::SuspensionHook(bool active)
528 {
529 // Implemented in subclasses
530 }
531
532
533 void
Suspend(char * label)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
Perform(perform_code d,void * arg)556 BWindowScreen::Perform(perform_code d, void* arg)
557 {
558 return inherited::Perform(d, arg);
559 }
560
561
562 // Reserved for future binary compatibility
_ReservedWindowScreen1()563 void BWindowScreen::_ReservedWindowScreen1() {}
_ReservedWindowScreen2()564 void BWindowScreen::_ReservedWindowScreen2() {}
_ReservedWindowScreen3()565 void BWindowScreen::_ReservedWindowScreen3() {}
_ReservedWindowScreen4()566 void BWindowScreen::_ReservedWindowScreen4() {}
567
568
569 status_t
_InitData(uint32 space,uint32 attributes)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
_DisposeData()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
_LockScreen(bool lock)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
_Activate()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
_Deactivate()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
_SetupAccelerantHooks()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
_ResetAccelerantHooks()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
_GetCardInfo()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
_Suspend()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
_Resume()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
_GetModeFromSpace(uint32 space,display_mode * dmode)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
_InitClone()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
_AssertDisplayMode(display_mode * displayMode)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(¤tMode);
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