2 * Copyright 2002-2009, Haiku. All Rights Reserved.
5 * Stefano Ceccherini (stefano.ceccherini@gmail.com),
6 * Carwyn Jones (turok2@currantbun.com)
9 * Distributed under the terms of the MIT License.
13 #include <WindowScreen.h>
20 #include <Application.h>
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>
32 using BPrivate::AppServerLink
;
35 //#define TRACE_WINDOWSCREEN 1
36 #if TRACE_WINDOWSCREEN
37 # define CALLED() printf("%s\n", __PRETTY_FUNCTION__);
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
;
52 static engine_token
*sEngineToken
;
55 // Helper methods which translates the pre r5 graphics methods to r5 ones
65 blit(int32 sx
, int32 sy
, int32 dx
, int32 dy
, int32 width
, int32 height
)
73 param
.height
= height
;
75 sAcquireEngineHook(B_2D_ACCELERATION
, 0xff, NULL
, &sEngineToken
);
76 sBlitRectHook(sEngineToken
, ¶m
, 1);
77 sReleaseEngineHook(sEngineToken
, NULL
);
82 // TODO: This function seems not to be exported through CardHookAt().
83 // At least, nothing I've tried uses it.
86 transparent_blit(int32 sx
, int32 sy
, int32 dx
, int32 dy
, int32 width
,
87 int32 height
, uint32 transparent_color
)
95 param
.height
= height
;
97 sAcquireEngineHook(B_2D_ACCELERATION
, 0xff, 0, &sEngineToken
);
98 sTransparentBlitHook(sEngineToken
, transparent_color
, ¶m
, 1);
99 sReleaseEngineHook(sEngineToken
, 0);
106 scaled_filtered_blit(int32 sx
, int32 sy
, int32 sw
, int32 sh
, int32 dx
, int32 dy
,
109 scaled_blit_params param
;
112 param
.src_width
= sw
;
113 param
.src_height
= sh
;
114 param
.dest_left
= dx
;
116 param
.dest_width
= dw
;
117 param
.dest_height
= dh
;
119 sAcquireEngineHook(B_2D_ACCELERATION
, 0xff, NULL
, &sEngineToken
);
120 sScaledFilteredBlitHook(sEngineToken
, ¶m
, 1);
121 sReleaseEngineHook(sEngineToken
, NULL
);
127 draw_rect_8(int32 sx
, int32 sy
, int32 sw
, int32 sh
, uint8 color_index
)
129 fill_rect_params param
;
135 sAcquireEngineHook(B_2D_ACCELERATION
, 0xff, NULL
, &sEngineToken
);
136 sFillRectHook(sEngineToken
, color_index
, ¶m
, 1);
137 sReleaseEngineHook(sEngineToken
, NULL
);
143 draw_rect_16(int32 sx
, int32 sy
, int32 sw
, int32 sh
, uint16 color
)
145 fill_rect_params param
;
151 sAcquireEngineHook(B_2D_ACCELERATION
, 0xff, NULL
, &sEngineToken
);
152 sFillRectHook(sEngineToken
, color
, ¶m
, 1);
153 sReleaseEngineHook(sEngineToken
, NULL
);
159 draw_rect_32(int32 sx
, int32 sy
, int32 sw
, int32 sh
, uint32 color
)
161 fill_rect_params param
;
167 sAcquireEngineHook(B_2D_ACCELERATION
, 0xff, NULL
, &sEngineToken
);
168 sFillRectHook(sEngineToken
, color
, ¶m
, 1);
169 sReleaseEngineHook(sEngineToken
, NULL
);
174 // #pragma mark - public API calls
178 set_mouse_position(int32 x
, int32 y
)
180 BMessage
command(IS_SET_MOUSE_POSITION
);
183 command
.AddPoint("where", BPoint(x
, y
));
184 _control_input_server_(&command
, &reply
);
191 BWindowScreen::BWindowScreen(const char *title
, uint32 space
, status_t
*error
,
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
,
200 uint32 attributes
= 0;
202 attributes
|= B_ENABLE_DEBUGGER
;
204 status_t status
= _InitData(space
, attributes
);
210 BWindowScreen::BWindowScreen(const char *title
, uint32 space
,
211 uint32 attributes
, status_t
*error
)
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
,
219 status_t status
= _InitData(space
, attributes
);
225 BWindowScreen::~BWindowScreen()
233 BWindowScreen::Quit(void)
242 BWindowScreen::ScreenConnected(bool active
)
244 // Implemented in subclasses
249 BWindowScreen::Disconnect()
252 if (fLockState
== 1) {
258 be_app
->ShowCursor();
263 BWindowScreen::WindowActivated(bool active
)
266 fWindowState
= active
;
267 if (active
&& fLockState
== 0 && fWorkState
)
273 BWindowScreen::WorkspaceActivated(int32 workspace
, bool state
)
279 if (fLockState
== 0 && fWindowState
) {
283 WindowActivated(true);
286 } else if (fLockState
)
292 BWindowScreen::ScreenChanged(BRect screenFrame
, color_space depth
)
294 // Implemented in subclasses
299 BWindowScreen::Hide()
309 BWindowScreen::Show()
318 BWindowScreen::SetColorList(rgb_color
*list
, int32 firstIndex
, int32 lastIndex
)
321 if (firstIndex
< 0 || lastIndex
> 255 || firstIndex
> lastIndex
)
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
];
333 uint8 colors
[3 * 256];
334 // the color table has 3 bytes per color
337 for (int32 x
= firstIndex
; x
<= lastIndex
; x
++) {
338 fPalette
[x
] = list
[x
- firstIndex
];
339 // update our local palette as well
341 colors
[j
++] = fPalette
[x
].red
;
342 colors
[j
++] = fPalette
[x
].green
;
343 colors
[j
++] = fPalette
[x
].blue
;
346 if (fAddonImage
>= 0) {
347 set_indexed_colors setIndexedColors
348 = (set_indexed_colors
)fGetAccelerantHook(B_SET_INDEXED_COLORS
,
350 if (setIndexedColors
!= NULL
) {
351 setIndexedColors(255, 0,
356 // TODO: Tell the app_server about our changes
358 BScreen
screen(this);
359 screen
.WaitForRetrace();
367 BWindowScreen::SetSpace(uint32 space
)
372 status_t status
= _GetModeFromSpace(space
, &mode
);
374 status
= _AssertDisplayMode(&mode
);
381 BWindowScreen::CanControlFrameBuffer()
383 return (fCardInfo
.flags
& B_FRAME_BUFFER_CONTROL
) != 0;
388 BWindowScreen::SetFrameBuffer(int32 width
, int32 height
)
391 display_mode highMode
= *fDisplayMode
;
392 highMode
.flags
|= B_SCROLL
;
394 highMode
.virtual_height
= (int16
)height
;
395 highMode
.virtual_width
= (int16
)width
;
397 display_mode lowMode
= highMode
;
398 display_mode mode
= highMode
;
400 BScreen
screen(this);
401 status_t status
= screen
.ProposeMode(&mode
, &lowMode
, &highMode
);
403 status
= _AssertDisplayMode(&mode
);
410 BWindowScreen::MoveDisplayArea(int32 x
, int32 y
)
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
;
428 BWindowScreen::IOBase()
437 BWindowScreen::ColorList()
445 BWindowScreen::FrameBufferInfo()
448 return &fFrameBufferInfo
;
453 BWindowScreen::CardHookAt(int32 index
)
459 graphics_card_hook hook
= NULL
;
462 case 5: // 8 bit fill rect
464 hook
= (graphics_card_hook
)draw_rect_8
;
466 case 6: // 32 bit fill rect
468 hook
= (graphics_card_hook
)draw_rect_32
;
470 case 7: // screen to screen blit
472 hook
= (graphics_card_hook
)blit
;
474 case 8: // screen to screen scaled filtered blit
475 if (sScaledFilteredBlitHook
)
476 hook
= (graphics_card_hook
)scaled_filtered_blit
;
478 case 10: // sync aka wait for graphics card idle
480 hook
= (graphics_card_hook
)card_sync
;
482 case 13: // 16 bit fill rect
484 hook
= (graphics_card_hook
)draw_rect_16
;
495 BWindowScreen::CardInfo()
503 BWindowScreen::RegisterThread(thread_id thread
)
509 status
= acquire_sem(fDebugSem
);
510 } while (status
== B_INTERRUPTED
);
515 void *newDebugList
= realloc(fDebugThreads
,
516 (fDebugThreadCount
+ 1) * sizeof(thread_id
));
517 if (newDebugList
!= NULL
) {
518 fDebugThreads
= (thread_id
*)newDebugList
;
519 fDebugThreads
[fDebugThreadCount
] = thread
;
522 release_sem(fDebugSem
);
527 BWindowScreen::SuspensionHook(bool active
)
529 // Implemented in subclasses
534 BWindowScreen::Suspend(char* label
)
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);
545 activate_workspace(fDebugWorkspace
);
548 suspend_thread(find_thread(NULL
));
556 BWindowScreen::Perform(perform_code d
, void* arg
)
558 return inherited::Perform(d
, arg
);
562 // Reserved for future binary compatibility
563 void BWindowScreen::_ReservedWindowScreen1() {}
564 void BWindowScreen::_ReservedWindowScreen2() {}
565 void BWindowScreen::_ReservedWindowScreen3() {}
566 void BWindowScreen::_ReservedWindowScreen4() {}
570 BWindowScreen::_InitData(uint32 space
, uint32 attributes
)
574 fDebugState
= attributes
& B_ENABLE_DEBUGGER
;
575 fDebugThreadCount
= 0;
576 fDebugThreads
= NULL
;
579 fAttributes
= attributes
;
580 // TODO: not really used right now, but should probably be known by
583 fWorkspaceIndex
= fDebugWorkspace
= current_workspace();
587 fOriginalDisplayMode
= NULL
;
592 fActivateState
= false;
595 status_t status
= B_ERROR
;
597 fOriginalDisplayMode
= new display_mode
;
598 fDisplayMode
= new display_mode
;
600 BScreen
screen(this);
601 status
= screen
.GetMode(fOriginalDisplayMode
);
605 status
= screen
.GetModeList(&fModeList
, &fModeCount
);
609 status
= _GetModeFromSpace(space
, fDisplayMode
);
613 status
= _GetCardInfo();
617 fDebugSem
= create_sem(1, "WindowScreen debug sem");
618 if (fDebugSem
< B_OK
)
619 throw (status_t
)fDebugSem
;
621 memcpy(fPalette
, screen
.ColorMap()->color_list
, sizeof(fPalette
));
622 fActivateState
= false;
626 } catch (std::bad_alloc
) {
627 status
= B_NO_MEMORY
;
628 } catch (status_t error
) {
642 BWindowScreen::_DisposeData()
646 if (fAddonImage
>= 0) {
647 unload_add_on(fAddonImage
);
651 delete_sem(fDebugSem
);
655 activate_workspace(fDebugWorkspace
);
659 delete fOriginalDisplayMode
;
660 fOriginalDisplayMode
= NULL
;
670 BWindowScreen::_LockScreen(bool lock
)
672 if (fActivateState
== lock
)
675 // TODO: the BWindowScreen should use the same mechanism as BDirectWindows!
676 BPrivate::AppServerLink link
;
678 link
.StartMessage(AS_DIRECT_SCREEN_LOCK
);
679 link
.Attach
<bool>(lock
);
681 status_t status
= B_ERROR
;
682 if (link
.FlushWithReply(status
) == B_OK
&& status
== B_OK
)
683 fActivateState
= lock
;
690 BWindowScreen::_Activate()
693 status_t status
= _AssertDisplayMode(fDisplayMode
);
697 status
= _SetupAccelerantHooks();
701 if (!fActivateState
) {
702 status
= _LockScreen(true);
707 be_app
->HideCursor();
709 SetColorList(fPalette
);
710 if (fDebugState
&& !fDebugFirst
) {
711 SuspensionHook(true);
715 ScreenConnected(true);
723 BWindowScreen::_Deactivate()
727 if (fDebugState
&& !fDebugFirst
) {
729 SuspensionHook(false);
731 ScreenConnected(false);
733 if (fActivateState
) {
734 status_t status
= _LockScreen(false);
738 BScreen
screen(this);
739 SetColorList((rgb_color
*)screen
.ColorMap()->color_list
);
742 _AssertDisplayMode(fOriginalDisplayMode
);
743 _ResetAccelerantHooks();
745 be_app
->ShowCursor();
752 BWindowScreen::_SetupAccelerantHooks()
756 status_t status
= B_OK
;
758 status
= _InitClone();
760 _ResetAccelerantHooks();
762 if (status
== B_OK
) {
763 sWaitIdleHook
= fWaitEngineIdle
= (wait_engine_idle
)
764 fGetAccelerantHook(B_WAIT_ENGINE_IDLE
, NULL
);
766 = (release_engine
)fGetAccelerantHook(B_RELEASE_ENGINE
, NULL
);
768 = (acquire_engine
)fGetAccelerantHook(B_ACQUIRE_ENGINE
, NULL
);
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
);
789 BWindowScreen::_ResetAccelerantHooks()
795 sFillRectHook
= NULL
;
796 sBlitRectHook
= NULL
;
797 sTransparentBlitHook
= NULL
;
798 sScaledFilteredBlitHook
= NULL
;
799 sWaitIdleHook
= NULL
;
801 sAcquireEngineHook
= NULL
;
802 sReleaseEngineHook
= NULL
;
804 fWaitEngineIdle
= NULL
;
811 BWindowScreen::_GetCardInfo()
815 BScreen
screen(this);
817 status_t status
= screen
.GetMode(&mode
);
822 switch(mode
.space
& 0x0fff) {
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
;
846 if (mode
.space
& 0x10)
847 memcpy(fCardInfo
.rgba_order
, "rgba", 4);
849 memcpy(fCardInfo
.rgba_order
, "bgra", 4);
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
;
858 link
.StartMessage(AS_GET_FRAME_BUFFER_CONFIG
);
859 link
.Attach
<screen_id
>(screen
.ID());
861 status_t result
= B_ERROR
;
862 if (link
.FlushWithReply(result
) < B_OK
|| result
< B_OK
)
865 frame_buffer_config config
;
866 link
.Read
<frame_buffer_config
>(&config
);
868 fCardInfo
.frame_buffer
= config
.frame_buffer
;
869 fCardInfo
.bytes_per_row
= config
.bytes_per_row
;
876 BWindowScreen::_Suspend()
882 status
= acquire_sem(fDebugSem
);
883 } while (status
== B_INTERRUPTED
);
888 // Suspend all the registered threads
889 for (int32 i
= 0; i
< fDebugThreadCount
; i
++) {
891 suspend_thread(fDebugThreads
[i
]);
894 graphics_card_info
*info
= CardInfo();
895 size_t fbSize
= info
->bytes_per_row
* info
->height
;
897 // Save the content of the frame buffer into the local buffer
898 fDebugFrameBuffer
= (char *)malloc(fbSize
);
899 memcpy(fDebugFrameBuffer
, info
->frame_buffer
, fbSize
);
904 BWindowScreen::_Resume()
907 graphics_card_info
*info
= CardInfo();
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
;
915 // Resume all the registered threads
916 for (int32 i
= 0; i
< fDebugThreadCount
; i
++) {
917 resume_thread(fDebugThreads
[i
]);
920 release_sem(fDebugSem
);
925 BWindowScreen::_GetModeFromSpace(uint32 space
, display_mode
*dmode
)
931 if (!BPrivate::get_mode_parameter(space
, width
, height
, colorSpace
))
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
));
948 BWindowScreen::_InitClone()
952 if (fAddonImage
>= 0)
955 BScreen
screen(this);
958 link
.StartMessage(AS_GET_ACCELERANT_PATH
);
959 link
.Attach
<screen_id
>(screen
.ID());
961 status_t status
= B_ERROR
;
962 if (link
.FlushWithReply(status
) < B_OK
|| status
< B_OK
)
965 BString accelerantPath
;
966 link
.ReadString(accelerantPath
);
968 link
.StartMessage(AS_GET_DRIVER_PATH
);
969 link
.Attach
<screen_id
>(screen
.ID());
972 if (link
.FlushWithReply(status
) < B_OK
|| status
< B_OK
)
976 link
.ReadString(driverPath
);
978 fAddonImage
= load_add_on(accelerantPath
.String());
979 if (fAddonImage
< B_OK
) {
980 fprintf(stderr
, "InitClone: cannot load accelerant image\n");
984 status
= get_image_symbol(fAddonImage
, B_ACCELERANT_ENTRY_POINT
,
985 B_SYMBOL_TYPE_TEXT
, (void**)&fGetAccelerantHook
);
987 fprintf(stderr
, "InitClone: cannot get accelerant entry point\n");
988 unload_add_on(fAddonImage
);
990 return B_NOT_SUPPORTED
;
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
);
999 return B_NOT_SUPPORTED
;
1002 status
= cloneHook((void*)driverPath
.String());
1003 if (status
< B_OK
) {
1004 fprintf(stderr
, "InitClone: cannot clone accelerant\n");
1005 unload_add_on(fAddonImage
);
1014 BWindowScreen::_AssertDisplayMode(display_mode
* displayMode
)
1018 BScreen
screen(this);
1020 display_mode currentMode
;
1021 status_t status
= screen
.GetMode(¤tMode
);
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",
1036 memcpy(fDisplayMode
, displayMode
, sizeof(display_mode
));
1039 status
= _GetCardInfo();
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;