From 272b2685eded8722b73a384060f1301a95eb0064 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 30 Mar 2004 07:29:49 +0000 Subject: [PATCH] WindowScreen implemented by Caz and myself, fully working (well, at least with the pageflipper demo) on BeOS R5. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7112 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/game/Jamfile | 3 +- src/kits/game/WindowScreen.cpp | 931 +++++++++++++++++++++++++++++++-- 2 files changed, 881 insertions(+), 53 deletions(-) diff --git a/src/kits/game/Jamfile b/src/kits/game/Jamfile index 7790ea2ebc..bddc891b38 100644 --- a/src/kits/game/Jamfile +++ b/src/kits/game/Jamfile @@ -19,8 +19,9 @@ SharedLibrary game : GSUtility.cpp ; -# Hack to have DirectWindow.cpp include the R5 header. +# Hack to have DirectWindow.cpp and WindowScreen.cpp include the R5 header. PrependObjectHdrs DirectWindow.cpp : /boot/develop/headers/be/interface ; +PrependObjectHdrs WindowScreen.cpp : /boot/develop/headers/be/interface ; LinkSharedOSLibs libgame.so : be libmedia.so diff --git a/src/kits/game/WindowScreen.cpp b/src/kits/game/WindowScreen.cpp index fdbdfcc678..b4c4bfe2ee 100644 --- a/src/kits/game/WindowScreen.cpp +++ b/src/kits/game/WindowScreen.cpp @@ -1,130 +1,553 @@ /* - * Copyright 2002, Marcus Overhagen. All rights reserved. + * Copyright 2003-2004, + * Stefano Ceccherini (burton666@libero.it). + * Carwyn Jones (turok2@currantbun.com) + * All rights reserved. * Distributed under the terms of the MIT License. */ +#include +#include #include +#include +#include +#include -void set_mouse_position(int32 x, int32 y) +#include "R5_AppServerLink.h" + +// WindowScreen commands +#define WS_PROPOSE_MODE 0x00000102 +#define WS_MOVE_DISPLAY 0x00000108 +#define WS_GET_FRAMEBUFFER 0x00000eed +#define WS_GET_ACCELERANT_NAME 0x00000ef4 +#define WS_GET_DRIVER_NAME 0x00000ef5 +#define WS_GET_DISPLAY_MODE 0x00000efd +#define WS_DISPLAY_UTILS 0x00000ef9 +#define WS_SWITCH_WORKSPACE 0x00000f26 +#define WS_SET_PALETTE 0x00000f27 +#define WS_SET_FULLSCREEN 0x00000881 + + +static const uint32 WS_SET_MOUSE_POSITION = 'Ismp'; + + +// WindowScreen Window flag (not defined anywhere else) +#define WS_SPECIAL_FLAG 0x10000 + + +#if TRACE_WINDOWSCREEN +#define CALLED() printf("%s\n", __PRETTY_FUNCTION__); +#else +#define CALLED() ; +#endif + +// TODO: Move this declaration somewhere else +_IMPEXP_BE status_t _control_input_server_(BMessage *command, BMessage *reply); + +static graphics_card_info card_info_global; +fill_rectangle fill_rect_global; +screen_to_screen_blit blit_rect_global; +screen_to_screen_transparent_blit trans_blit_rect_global; +screen_to_screen_scaled_filtered_blit scaled_filtered_blit_rect_global; +wait_engine_idle wait_idle_global; +engine_token *et_global; +acquire_engine acquire_engine_global; +release_engine release_engine_global; + + +// Helper methods which translates the pre r5 graphics methods to r5 ones +static int32 +sync() { + wait_idle_global(); + return 0; } -BWindowScreen::BWindowScreen(const char *title, - uint32 space, - status_t *error, - bool debug_enable) - : BWindow(BRect(0,0,0,0), title, B_UNTYPED_WINDOW, B_ASYNCHRONOUS_CONTROLS, B_CURRENT_WORKSPACE) // XXX this needs to be fixed +static int32 +blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width, int32 height) { + blit_params param; + param.src_left = sx; + param.src_top = sy; + param.dest_left = dx; + param.dest_top = dy; + param.width = width; + param.height = height; + + acquire_engine_global(1, 0xff, 0, &et_global); + blit_rect_global(et_global, ¶m, 1); + release_engine_global(et_global, 0); + return 0; } -BWindowScreen::BWindowScreen(const char *title, - uint32 space, - uint32 attributes, - status_t *error) - : BWindow(BRect(0,0,0,0), title, B_UNTYPED_WINDOW, B_ASYNCHRONOUS_CONTROLS, B_CURRENT_WORKSPACE) // XXX this needs to be fixed +static int32 +transparent_blit(int32 sx, int32 sy, int32 dx, int32 dy, + int32 width, int32 height, uint32 transparent_color) { + blit_params param; + param.src_left = sx; + param.src_top = sy; + param.dest_left = dx; + param.dest_top = dy; + param.width = width; + param.height = height; + + acquire_engine_global(1, 0xff, 0, &et_global); + trans_blit_rect_global(et_global, transparent_color, ¶m, 1); + release_engine_global(et_global, 0); + return 0; +} + + +static int32 +scaled_filtered_blit(int32 sx, int32 sy, int32 sw, int32 sh, int32 dx, int32 dy, int32 dw, int32 dh) +{ + scaled_blit_params param; + param.src_left = sx; + param.src_top = sy; + param.src_width = sw; + param.src_height = sh; + param.dest_left = dx; + param.dest_top = dy; + param.dest_width = dw; + param.dest_height = dh; + + acquire_engine_global(1, 0xff, 0, &et_global); + scaled_filtered_blit_rect_global(et_global, ¶m, 1); + release_engine_global(et_global, 0); + return 0; +} + + +static int32 +draw_rect_8(int32 sx, int32 sy, int32 sw, int32 sh, uint8 color_index) +{ + fill_rect_params param; + param.left = sx; + param.top = sy; + param.right = sw; + param.bottom = sh; + + acquire_engine_global(1, 0xff, 0, &et_global); + fill_rect_global(et_global, color_index, ¶m, 1); + release_engine_global(et_global, 0); + return 0; +} + + +static int32 +draw_rect_16(int32 sx, int32 sy, int32 sw, int32 sh, uint16 color) +{ + fill_rect_params param; + param.left = sx; + param.top = sy; + param.right = sw; + param.bottom = sh; + + acquire_engine_global(1, 0xff, 0, &et_global); + fill_rect_global(et_global, color, ¶m, 1); + release_engine_global(et_global, 0); + return 0; +} + + +static int32 +draw_rect_32(int32 sx, int32 sy, int32 sw, int32 sh, uint32 color) +{ + fill_rect_params param; + param.left = sx; + param.top = sy; + param.right = sw; + param.bottom = sh; + + acquire_engine_global(1, 0xff, 0, &et_global); + fill_rect_global(et_global, color, ¶m, 1); + release_engine_global(et_global, 0); + return 0; +} + + +static void +mode2parms(uint32 space, uint32 *out_space, int32 *width, int32 *height) +{ + switch (space) { + case B_8_BIT_640x480: + *out_space = B_CMAP8; + *width = 640; *height = 480; + break; + case B_8_BIT_800x600: + *out_space = B_CMAP8; + *width = 800; *height = 600; + break; + case B_8_BIT_1024x768: + *out_space = B_CMAP8; + *width = 1024; *height = 768; + break; + case B_8_BIT_1280x1024: + *out_space = B_CMAP8; + *width = 1280; *height = 1024; + break; + case B_8_BIT_1600x1200: + *out_space = B_CMAP8; + *width = 1600; *height = 1200; + break; + case B_16_BIT_640x480: + *out_space = B_RGB16; + *width = 640; *height = 480; + break; + case B_16_BIT_800x600: + *out_space = B_RGB16; + *width = 800; *height = 600; + break; + case B_16_BIT_1024x768: + *out_space = B_RGB16; + *width = 1024; *height = 768; + break; + case B_16_BIT_1280x1024: + *out_space = B_RGB16; + *width = 1280; *height = 1024; + break; + case B_16_BIT_1600x1200: + *out_space = B_RGB16; + *width = 1600; *height = 1200; + break; + case B_32_BIT_640x480: + *out_space = B_RGB32; + *width = 640; *height = 480; + break; + case B_32_BIT_800x600: + *out_space = B_RGB32; + *width = 800; *height = 600; + break; + case B_32_BIT_1024x768: + *out_space = B_RGB32; + *width = 1024; *height = 768; + break; + case B_32_BIT_1280x1024: + *out_space = B_RGB32; + *width = 1280; *height = 1024; + break; + case B_32_BIT_1600x1200: + *out_space = B_RGB32; + *width = 1600; *height = 1200; + break; + case B_8_BIT_1152x900: + *out_space = B_CMAP8; + *width = 1152; *height = 900; + break; + case B_16_BIT_1152x900: + *out_space = B_RGB16; + *width = 1152; *height = 900; + break; + case B_32_BIT_1152x900: + *out_space = B_RGB32; + *width = 1152; *height = 900; + break; + case B_15_BIT_640x480: + *out_space = B_RGB15; + *width = 640; *height = 480; + break; + case B_15_BIT_800x600: + *out_space = B_RGB15; + *width = 800; *height = 600; + break; + case B_15_BIT_1024x768: + *out_space = B_RGB15; + *width = 1024; *height = 768; + break; + case B_15_BIT_1280x1024: + *out_space = B_RGB15; + *width = 1280; *height = 1024; + break; + case B_15_BIT_1600x1200: + *out_space = B_RGB15; + *width = 1600; *height = 1200; + break; + case B_15_BIT_1152x900: + *out_space = B_RGB15; + *width = 1152; *height = 900; + break; + } +} + + +// BWindowScreen public API + +void +set_mouse_position(int32 x, int32 y) +{ + BMessage command(WS_SET_MOUSE_POSITION); + BMessage reply; + + command.AddPoint("where", BPoint(x, y)); + _control_input_server_(&command, &reply); +} + + +BWindowScreen::BWindowScreen(const char *title, uint32 space, status_t *error, bool debug_enable) + : + BWindow(BScreen().Frame(), title, B_TITLED_WINDOW, + WS_SPECIAL_FLAG | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE, + B_CURRENT_WORKSPACE) +{ + CALLED(); + uint32 attributes = 0; + if (debug_enable) + attributes |= B_ENABLE_DEBUGGER; + + *error = InitData(space, attributes); +} + + +BWindowScreen::BWindowScreen(const char *title, uint32 space, uint32 attributes, status_t *error) + : + BWindow(BScreen().Frame(), title, B_TITLED_WINDOW, + WS_SPECIAL_FLAG | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE, + B_CURRENT_WORKSPACE) +{ + CALLED(); + *error = InitData(space, attributes); } BWindowScreen::~BWindowScreen() { + Disconnect(); + if (addon_state == 1) + unload_add_on(addon_image); + + SetFullscreen(0); + + delete_sem(activate_sem); + delete_sem(debug_sem); + + if (debug_state) { + _BAppServerLink_ link; + link.fSession->swrite_l(WS_SWITCH_WORKSPACE); + link.fSession->swrite_l(debug_workspace); + link.fSession->sync(); + } + + free(new_space); + free(old_space); + free(mode_list); } void BWindowScreen::Quit(void) { + Disconnect(); + BWindow::Quit(); } void BWindowScreen::ScreenConnected(bool active) { + // Implemented in subclasses } void BWindowScreen::Disconnect() { + if (lock_state == 1) { + if (debug_state) + debug_first = true; + SetActiveState(0); + } } - void BWindowScreen::WindowActivated(bool active) { + window_state = active; + if(active && lock_state == 0 && work_state) + SetActiveState(1); } - void BWindowScreen::WorkspaceActivated(int32 ws, bool state) { + work_state = state; + if (state) { + if (lock_state == 0 && window_state) { + SetActiveState(1); + if (!IsHidden()) { + Activate(true); + WindowActivated(true); + } + } + } else { + if (lock_state) + SetActiveState(0); + } } void -BWindowScreen::ScreenChanged(BRect screen_size, - color_space depth) +BWindowScreen::ScreenChanged(BRect screen_size, color_space depth) { + // Implemented in subclasses } void BWindowScreen::Hide() { + if (lock_state == 1) { + if (debug_state) + debug_first = true; + SetActiveState(0); + } + + BWindow::Hide(); } void BWindowScreen::Show() { + BWindow::Show(); + if (!activate_state) { + release_sem(activate_sem); + activate_state = true; + } } void -BWindowScreen::SetColorList(rgb_color *list, - int32 first_index, - int32 last_index) +BWindowScreen::SetColorList(rgb_color *list, int32 first_index, int32 last_index) { + if (first_index < 0 || last_index > 255 || first_index > last_index) + return; + + if (Lock()) { + if (!activate_state) { + //If we aren't active, we just change our local palette + for (int32 x = first_index; x <= last_index; x++) + colorList[x] = list[x]; + } else { + uint32 colorCount = last_index - first_index + 1; + if (addon_state == 1) { + set_indexed_colors sic = (set_indexed_colors)m_gah(B_SET_INDEXED_COLORS, NULL); + if (sic != NULL) + sic(colorCount, first_index, (uint8*)colorList, 0); + } + + BScreen screen(this); + screen.WaitForRetrace(); + // Update our local palette too. We're doing this between two + // WaitForRetrace() calls so nobody will notice. + for (int32 x = first_index; x <= last_index; x++) + colorList[x] = list[x]; + + // Tell the app_server about our changes + _BAppServerLink_ link; + link.fSession->swrite_l(WS_SET_PALETTE); + link.fSession->swrite_l(screen_index); + link.fSession->swrite_l(first_index); + link.fSession->swrite_l(last_index); + link.fSession->swrite(colorCount * sizeof(rgb_color), colorList); + link.fSession->sync(); + + screen.WaitForRetrace(); + } + + Unlock(); + } } status_t BWindowScreen::SetSpace(uint32 space) { - return B_ERROR; + display_mode mode; + status_t status = GetModeFromSpace(space, &mode); + if (status == B_OK) + status = AssertDisplayMode(&mode); + return status; } bool BWindowScreen::CanControlFrameBuffer() { - return false; + bool retval = false; + if (addon_state <= 1 && (card_info.flags & B_FRAME_BUFFER_CONTROL)) + retval = true; + + return retval; } status_t -BWindowScreen::SetFrameBuffer(int32 width, - int32 height) +BWindowScreen::SetFrameBuffer(int32 width, int32 height) { - return B_ERROR; + display_mode highMode = *new_space; + + highMode.virtual_height = (int16)height; + highMode.virtual_width = (int16)width; + + display_mode lowMode = highMode; + display_mode mode = highMode; + + // equivalent to BScreen::ProposeMode() + _BAppServerLink_ link; + link.fSession->swrite_l(WS_DISPLAY_UTILS); + link.fSession->swrite_l(screen_index); + link.fSession->swrite_l(WS_PROPOSE_MODE); + link.fSession->swrite(sizeof(display_mode), &highMode); + link.fSession->swrite(sizeof(display_mode), &mode); + link.fSession->swrite(sizeof(display_mode), &lowMode); + link.fSession->sync(); + + status_t status; + link.fSession->sread(sizeof(status), &status); + link.fSession->sread(sizeof(display_mode), &mode); + + // If the mode is supported, change the workspace + // to that mode. + if (status == B_OK) + status = AssertDisplayMode(&mode); + + return status; } status_t -BWindowScreen::MoveDisplayArea(int32 x, - int32 y) +BWindowScreen::MoveDisplayArea(int32 x, int32 y) { - return B_ERROR; + _BAppServerLink_ link; + link.fSession->swrite_l(WS_DISPLAY_UTILS); + link.fSession->swrite_l(screen_index); + link.fSession->swrite_l(WS_MOVE_DISPLAY); + link.fSession->swrite(sizeof(int16), (int16*)&x); + link.fSession->swrite(sizeof(int16), (int16*)&y); + link.fSession->sync(); + + status_t status; + link.fSession->sread(sizeof(status), &status); + + if (status == B_OK) { + format_info.display_x = x; + format_info.display_y = y; + new_space->h_display_start = x; + new_space->v_display_start = y; + } + return status; } void * BWindowScreen::IOBase() { + // Not supported return NULL; } @@ -132,46 +555,117 @@ BWindowScreen::IOBase() rgb_color * BWindowScreen::ColorList() { - return NULL; + return colorList; } frame_buffer_info * BWindowScreen::FrameBufferInfo() { - return NULL; + return &format_info; } graphics_card_hook BWindowScreen::CardHookAt(int32 index) { - return 0; + if (addon_state != 1) + return 0; + + graphics_card_hook hook = NULL; + + switch (index) { + case 5: // 8 bit fill rect + hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0); + fill_rect = (fill_rectangle)hook; + fill_rect_global = fill_rect; + hook = (graphics_card_hook)draw_rect_8; + break; + case 6: // 32 bit fill rect + hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0); + fill_rect = (fill_rectangle)hook; + fill_rect_global = fill_rect; + hook = (graphics_card_hook)draw_rect_32; + break; + case 7: // screen to screen blit + hook = (graphics_card_hook)m_gah(B_SCREEN_TO_SCREEN_BLIT, 0); + blit_rect = (screen_to_screen_blit)hook; + blit_rect_global = blit_rect; + hook = (graphics_card_hook)blit; + break; + case 8: // screen to screen scaled filtered blit + hook = (graphics_card_hook)m_gah(B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT, 0); + scaled_filtered_blit_rect = (screen_to_screen_scaled_filtered_blit)hook; + scaled_filtered_blit_rect_global = scaled_filtered_blit_rect; + hook = (graphics_card_hook)scaled_filtered_blit; + break; + case 10: // sync aka wait for graphics card idle + hook = (graphics_card_hook)sync; + break; + case 13: // 16 bit fill rect + hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0); + fill_rect = (fill_rectangle)hook; + fill_rect_global = fill_rect; + hook = (graphics_card_hook)draw_rect_16; + break; + default: + break; + } + + return hook; } graphics_card_info * BWindowScreen::CardInfo() { - return NULL; + return &card_info; } void BWindowScreen::RegisterThread(thread_id id) { + CALLED(); + while (acquire_sem(debug_sem) == B_INTERRUPTED) + ; + ++debug_list_count; + debug_list = (thread_id *)realloc(debug_list, debug_list_count * sizeof(thread_id)); + debug_list[debug_list_count - 1] = id; + + release_sem(debug_sem); } void BWindowScreen::SuspensionHook(bool active) { + // Implemented in subclasses } void BWindowScreen::Suspend(char *label) { + CALLED(); + if (debug_state) { + fprintf(stderr, "## Debugger(\"%s\").", label); + fprintf(stderr, " Press Alt-F%ld or Cmd-F%ld to resume.\n", space0 + 1, space0 + 1); + + if (IsLocked()) + Unlock(); + + // Switch to debug workspace + _BAppServerLink_ link; + link.fSession->swrite_l(WS_SWITCH_WORKSPACE); + link.fSession->swrite_l(debug_workspace); + link.fSession->sync(); + + // Suspend ourself + suspend_thread(find_thread(NULL)); + + Lock(); + } } @@ -179,7 +673,7 @@ status_t BWindowScreen::Perform(perform_code d, void *arg) { - return B_ERROR; + return inherited::Perform(d, arg); } @@ -216,81 +710,414 @@ BWindowScreen::_ReservedWindowScreen4() BRect -BWindowScreen::CalcFrame(int32 index, - int32 space, - display_mode *dmode) +BWindowScreen::CalcFrame(int32 index, int32 space, display_mode *dmode) { - BRect dummy; - return dummy; + BScreen screen; + if (dmode) + screen.GetMode(dmode); + + return screen.Frame(); } int32 BWindowScreen::SetFullscreen(int32 enable) { - return 0; + a_session->swrite_l(WS_SET_FULLSCREEN); + a_session->swrite_l(server_token); + a_session->swrite_l(enable); + a_session->sync(); + + int32 result, retval; + + a_session->sread(sizeof(result), &result); + a_session->sread(sizeof(retval), &retval); + + return retval; } - status_t -BWindowScreen::InitData(uint32 space, - uint32 attributes) +BWindowScreen::InitData(uint32 space, uint32 attributes) { - return B_ERROR; + BScreen screen(this); + debug_state = attributes & B_ENABLE_DEBUGGER; + debug_list_count = 0; + debug_list = 0; + debug_first = true; + + debug_sem = create_sem(1, "WindowScreen debug sem"); + old_space = (display_mode *)calloc(0x1, sizeof(display_mode)); + new_space = (display_mode *)calloc(0x1, sizeof(display_mode)); + + screen.GetModeList(&mode_list, &mode_count); + + _attributes = attributes; + + display_mode *n_space = new_space; + screen_index = 0; + lock_state = 0; + addon_state = 0; + direct_enable = 0; + window_state = 0; + + space_mode = 1; + + GetModeFromSpace(space, n_space); + + space0 = 0; + + SetWorkspaces(B_CURRENT_WORKSPACE); + + SetFullscreen(1); + work_state = 1; + debug_workspace = 0; + const color_map *map = screen.ColorMap(); + memcpy(colorList, map->color_list, 256); + + GetCardInfo(); + activate_sem = create_sem(0, "WindowScreen start lock"); + activate_state = 0; + + + return B_OK; } status_t BWindowScreen::SetActiveState(int32 state) { - return B_ERROR; + status_t status = B_ERROR; + if (state == 1) { + be_app->HideCursor(); + if (be_app->IsCursorHidden() + && (status = SetLockState(1)) == B_OK) { + status = AssertDisplayMode(new_space); + if (status == B_OK) { + if (!activate_state) { + while (acquire_sem(activate_sem) == B_INTERRUPTED) + ; + } + SetColorList(colorList); + if (debug_state && !debug_first) { + SuspensionHook(true); + Resume(); + } else { + debug_first = true; + ScreenConnected(true); + } + if (status == B_OK) + return status; + + } else + SetLockState(0); + + be_app->ShowCursor(); + } + } else { + if (debug_state && !debug_first) { + Suspend(); + SuspensionHook(false); + } else + ScreenConnected(false); + + status = SetLockState(0); + if (status == B_OK) { + be_app->ShowCursor(); + if (activate_state) { + _BAppServerLink_ link; + link.fSession->swrite_l(0xF27); + link.fSession->swrite_l(screen_index); + link.fSession->swrite_l(0); + link.fSession->swrite_l(255); + const color_map *colorMap = system_colors(); + link.fSession->swrite(256 * sizeof(rgb_color), const_cast(colorMap->color_list)); + link.fSession->sync(); + } + } + } + return status; } - status_t BWindowScreen::SetLockState(int32 state) { - return B_ERROR; + if(addon_state == 1 && state == 1) { + m_wei(); + fill_rect_global = NULL; + blit_rect_global = NULL; + trans_blit_rect_global = NULL; + scaled_filtered_blit_rect_global = NULL; + wait_idle_global = NULL; + et_global = NULL; + acquire_engine_global = NULL; + release_engine_global = NULL; + } + + _BAppServerLink_ link; + link.fSession->swrite_l(0x00000efb); + link.fSession->swrite_l(screen_index); + link.fSession->swrite_l(state); + link.fSession->swrite_l(server_token); + link.fSession->sync(); + + status_t status; + link.fSession->sread(sizeof(status), &status); + + if (status == B_NO_ERROR) { + lock_state = state; + if (state == 1) { + if (addon_state == 0) { + status = InitClone(); + + if (status == B_OK) { + addon_state = 1; + m_wei = (wait_engine_idle)m_gah(B_WAIT_ENGINE_IDLE, NULL); + m_re = (release_engine)m_gah(B_RELEASE_ENGINE, NULL); + m_ae = (acquire_engine)m_gah(B_ACQUIRE_ENGINE, NULL); + } else + addon_state = -1; + } + + if (addon_state == 1 && state == 1) { + fill_rect_global = fill_rect; + blit_rect_global = blit_rect; + trans_blit_rect_global = trans_blit_rect; + scaled_filtered_blit_rect_global = scaled_filtered_blit_rect; + wait_idle_global = m_wei; + et_global = et; + acquire_engine_global = m_ae; + release_engine_global = m_re; + m_wei(); + } + } + } + + return status; } void BWindowScreen::GetCardInfo() { + BScreen screen(this); + frame_buffer_config config; + + display_mode mode; + uint32 bits_per_pixel; + + card_info.version = 2; + card_info.id = 0; + screen.GetMode(&mode); + + switch(mode.space & 0x0fff) { + case B_CMAP8: + bits_per_pixel = 8; + break; + case B_RGB16: + bits_per_pixel = 16; + break; + case B_RGB32: + bits_per_pixel = 32; + break; + default: + bits_per_pixel = 0; + break; + } + card_info.bits_per_pixel = bits_per_pixel; + card_info.width = mode.virtual_width; + card_info.height = mode.virtual_height; + + if (mode.space & 0x10) + strncpy(card_info.rgba_order, "rgba", 4); + else + strncpy(card_info.rgba_order, "bgra", 4); + + card_info.flags = 0; + + if (mode.flags & B_SCROLL) + card_info.flags = B_FRAME_BUFFER_CONTROL; + if (mode.flags & B_PARALLEL_ACCESS) + card_info.flags |= B_PARALLEL_BUFFER_ACCESS; + + screen_id id = screen.ID(); + _BAppServerLink_ link; + link.fSession->swrite_l(WS_GET_FRAMEBUFFER); + link.fSession->swrite_l(id.id); + link.fSession->sync(); + + int32 result; + link.fSession->sread(sizeof(result), &result); + + if(result == B_NO_ERROR) { + link.fSession->sread(sizeof(frame_buffer_config), &config); + card_info.id = id.id; + card_info.frame_buffer = config.frame_buffer; + card_info.bytes_per_row = config.bytes_per_row; + } + memcpy(&card_info_global, &card_info, sizeof(graphics_card_info)); } void BWindowScreen::Suspend() { + CALLED(); + + while (acquire_sem(debug_sem) == B_INTERRUPTED) + ; + + // Suspend all the registered threads + for (int i = 0; i < debug_list_count; i++) { + snooze(10000); + suspend_thread(debug_list[i]); + } + + graphics_card_info *info = CardInfo(); + size_t fbSize = info->bytes_per_row * info->height; + + // Save the content of the frame buffer into the local buffer + debug_buffer = (char *)malloc(fbSize); + memcpy(debug_buffer, info->frame_buffer, fbSize); } void BWindowScreen::Resume() { + CALLED(); + graphics_card_info *info = CardInfo(); + + // Copy the content of the debug_buffer back into the frame buffer. + memcpy(info->frame_buffer, debug_buffer, info->bytes_per_row * info->height); + free(debug_buffer); + + // Resume all the registered threads + for (int i = 0; i < debug_list_count; i++) + resume_thread(debug_list[i]); + + release_sem(debug_sem); } status_t -BWindowScreen::GetModeFromSpace(uint32 space, - display_mode *dmode) +BWindowScreen::GetModeFromSpace(uint32 space, display_mode *dmode) { - return B_ERROR; + uint32 out_space; + int32 width, height; + status_t ret = B_ERROR; + + mode2parms(space, &out_space, &width, &height); + // mode2parms converts the space to actual width, height and color_space, e.g B_8_BIT_640x480 + + for (uint32 i = 0; i < mode_count; i++) { + if (mode_list[i].space == out_space && mode_list[i].virtual_width == width + && mode_list[i].virtual_height == height) { + + memcpy(dmode, &mode_list[i], sizeof(display_mode)); + ret = B_OK; + break; + } + } + + return ret; } status_t BWindowScreen::InitClone() { - return B_ERROR; + _BAppServerLink_ link; + link.fSession->swrite_l(WS_GET_ACCELERANT_NAME); + link.fSession->swrite_l(screen_index); + link.fSession->sync(); + + int32 result; + link.fSession->sread(sizeof(result), &result); + if (result != B_OK) + return result; + + link.fSession->sread(sizeof(result), &result); // read length of accelerant's name + + char *addonName = (char *)malloc((result + 1) * sizeof (char)); + link.fSession->sread(result, addonName); // read the accelerant's name + addonName[result] = '\0'; + + link.fSession->swrite_l(WS_GET_DRIVER_NAME); // get driver's name without the /dev/ + link.fSession->swrite_l(screen_index); + link.fSession->sync(); + + link.fSession->sread(sizeof(result), &result); + if (result != B_OK) + return result; + + link.fSession->sread(sizeof(result), &result); + // result now contains the length of the buffer needed for the drivers path name + + char *path = (char *)malloc((result + 1) * sizeof(char)); + link.fSession->sread(result, path); + path[result] = '\0'; + // path now contains the driver's name + + // load the accelerant + addon_image = load_add_on(addonName); + + free(addonName); + + if(addon_image < 0) + return B_ERROR; + + // now get the symbol for GetAccelerantHook m_gah + if (get_image_symbol(addon_image, "get_accelerant_hook", + B_SYMBOL_TYPE_ANY, (void **)&m_gah) < 0) + return B_ERROR; + + // now use m_gah to get a pointer to the accelerant's clone accelerant + clone_accelerant clone = (clone_accelerant)m_gah(B_CLONE_ACCELERANT, 0); + + if (!clone) + return B_ERROR; + + // test if the driver supports cloning of the accelerant, using the path we got earlier + result = clone((void *)path); + free(path); + + if (result != 0) { + unload_add_on(addon_image); + addon_image = -1; + } + + return result; } status_t BWindowScreen::AssertDisplayMode(display_mode *dmode) { - return B_ERROR; + status_t result; + _BAppServerLink_ link; + + link.fSession->swrite_l(WS_GET_DISPLAY_MODE); // check display_mode valid command + link.fSession->swrite_l(screen_index); + link.fSession->swrite(sizeof(display_mode), (void *)dmode); + link.fSession->sync(); + + link.fSession->sread(sizeof(result), &result); + + // if the result is B_OK, we copy the dmode to new_space + if (result == B_OK) { + memcpy(new_space, dmode, sizeof(display_mode)); + space_mode = 1; + } + GetCardInfo(); + + format_info.bits_per_pixel = card_info.bits_per_pixel; + format_info.bytes_per_row = card_info.bytes_per_row; + format_info.width = card_info.width; + format_info.height = card_info.height; + format_info.display_width = card_info.width; + format_info.display_height = card_info.height; + format_info.display_x = 0; + format_info.display_y = 0; + + return result; } - -