1 /* 2 * Copyright 2002-2004, 3 * Marcus Overhagen, 4 * Stefano Ceccherini (burton666@libero.it), 5 * Carwyn Jones (turok2@currantbun.com) 6 * All rights reserved. 7 * Distributed under the terms of the MIT License. 8 */ 9 10 #include <Application.h> 11 #include <Screen.h> 12 #include <WindowScreen.h> 13 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <string.h> 17 18 #include "R5_AppServerLink.h" 19 20 // WindowScreen commands 21 #define WS_PROPOSE_MODE 0x00000102 22 #define WS_MOVE_DISPLAY 0x00000108 23 #define WS_GET_FRAMEBUFFER 0x00000eed 24 #define WS_GET_ACCELERANT_NAME 0x00000ef4 25 #define WS_GET_DRIVER_NAME 0x00000ef5 26 #define WS_GET_DISPLAY_MODE 0x00000efd 27 #define WS_DISPLAY_UTILS 0x00000ef9 28 #define WS_SWITCH_WORKSPACE 0x00000f26 29 #define WS_SET_PALETTE 0x00000f27 30 #define WS_SET_FULLSCREEN 0x00000881 31 32 33 static const uint32 WS_SET_MOUSE_POSITION = 'Ismp'; 34 35 36 // WindowScreen Window flag (not defined anywhere else) 37 #define WS_SPECIAL_FLAG 0x10000 38 39 40 #if TRACE_WINDOWSCREEN 41 #define CALLED() printf("%s\n", __PRETTY_FUNCTION__); 42 #else 43 #define CALLED() ; 44 #endif 45 46 // TODO: Move this declaration somewhere else 47 _IMPEXP_BE status_t _control_input_server_(BMessage *command, BMessage *reply); 48 49 static graphics_card_info card_info_global; 50 fill_rectangle fill_rect_global; 51 screen_to_screen_blit blit_rect_global; 52 screen_to_screen_transparent_blit trans_blit_rect_global; 53 screen_to_screen_scaled_filtered_blit scaled_filtered_blit_rect_global; 54 wait_engine_idle wait_idle_global; 55 engine_token *et_global; 56 acquire_engine acquire_engine_global; 57 release_engine release_engine_global; 58 59 60 // Helper methods which translates the pre r5 graphics methods to r5 ones 61 static int32 62 sync() 63 { 64 wait_idle_global(); 65 return 0; 66 } 67 68 69 static int32 70 blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width, int32 height) 71 { 72 blit_params param; 73 param.src_left = sx; 74 param.src_top = sy; 75 param.dest_left = dx; 76 param.dest_top = dy; 77 param.width = width; 78 param.height = height; 79 80 acquire_engine_global(1, 0xff, 0, &et_global); 81 blit_rect_global(et_global, ¶m, 1); 82 release_engine_global(et_global, 0); 83 return 0; 84 } 85 86 87 static int32 88 transparent_blit(int32 sx, int32 sy, int32 dx, int32 dy, 89 int32 width, int32 height, uint32 transparent_color) 90 { 91 blit_params param; 92 param.src_left = sx; 93 param.src_top = sy; 94 param.dest_left = dx; 95 param.dest_top = dy; 96 param.width = width; 97 param.height = height; 98 99 acquire_engine_global(1, 0xff, 0, &et_global); 100 trans_blit_rect_global(et_global, transparent_color, ¶m, 1); 101 release_engine_global(et_global, 0); 102 return 0; 103 } 104 105 106 static int32 107 scaled_filtered_blit(int32 sx, int32 sy, int32 sw, int32 sh, int32 dx, int32 dy, 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 acquire_engine_global(1, 0xff, 0, &et_global); 120 scaled_filtered_blit_rect_global(et_global, ¶m, 1); 121 release_engine_global(et_global, 0); 122 return 0; 123 } 124 125 126 static int32 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 acquire_engine_global(1, 0xff, 0, &et_global); 136 fill_rect_global(et_global, color_index, ¶m, 1); 137 release_engine_global(et_global, 0); 138 return 0; 139 } 140 141 142 static int32 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 acquire_engine_global(1, 0xff, 0, &et_global); 152 fill_rect_global(et_global, color, ¶m, 1); 153 release_engine_global(et_global, 0); 154 return 0; 155 } 156 157 158 static int32 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 acquire_engine_global(1, 0xff, 0, &et_global); 168 fill_rect_global(et_global, color, ¶m, 1); 169 release_engine_global(et_global, 0); 170 return 0; 171 } 172 173 174 static void 175 mode2parms(uint32 space, uint32 *out_space, int32 *width, int32 *height) 176 { 177 switch (space) { 178 case B_8_BIT_640x480: 179 *out_space = B_CMAP8; 180 *width = 640; *height = 480; 181 break; 182 case B_8_BIT_800x600: 183 *out_space = B_CMAP8; 184 *width = 800; *height = 600; 185 break; 186 case B_8_BIT_1024x768: 187 *out_space = B_CMAP8; 188 *width = 1024; *height = 768; 189 break; 190 case B_8_BIT_1280x1024: 191 *out_space = B_CMAP8; 192 *width = 1280; *height = 1024; 193 break; 194 case B_8_BIT_1600x1200: 195 *out_space = B_CMAP8; 196 *width = 1600; *height = 1200; 197 break; 198 case B_16_BIT_640x480: 199 *out_space = B_RGB16; 200 *width = 640; *height = 480; 201 break; 202 case B_16_BIT_800x600: 203 *out_space = B_RGB16; 204 *width = 800; *height = 600; 205 break; 206 case B_16_BIT_1024x768: 207 *out_space = B_RGB16; 208 *width = 1024; *height = 768; 209 break; 210 case B_16_BIT_1280x1024: 211 *out_space = B_RGB16; 212 *width = 1280; *height = 1024; 213 break; 214 case B_16_BIT_1600x1200: 215 *out_space = B_RGB16; 216 *width = 1600; *height = 1200; 217 break; 218 case B_32_BIT_640x480: 219 *out_space = B_RGB32; 220 *width = 640; *height = 480; 221 break; 222 case B_32_BIT_800x600: 223 *out_space = B_RGB32; 224 *width = 800; *height = 600; 225 break; 226 case B_32_BIT_1024x768: 227 *out_space = B_RGB32; 228 *width = 1024; *height = 768; 229 break; 230 case B_32_BIT_1280x1024: 231 *out_space = B_RGB32; 232 *width = 1280; *height = 1024; 233 break; 234 case B_32_BIT_1600x1200: 235 *out_space = B_RGB32; 236 *width = 1600; *height = 1200; 237 break; 238 case B_8_BIT_1152x900: 239 *out_space = B_CMAP8; 240 *width = 1152; *height = 900; 241 break; 242 case B_16_BIT_1152x900: 243 *out_space = B_RGB16; 244 *width = 1152; *height = 900; 245 break; 246 case B_32_BIT_1152x900: 247 *out_space = B_RGB32; 248 *width = 1152; *height = 900; 249 break; 250 case B_15_BIT_640x480: 251 *out_space = B_RGB15; 252 *width = 640; *height = 480; 253 break; 254 case B_15_BIT_800x600: 255 *out_space = B_RGB15; 256 *width = 800; *height = 600; 257 break; 258 case B_15_BIT_1024x768: 259 *out_space = B_RGB15; 260 *width = 1024; *height = 768; 261 break; 262 case B_15_BIT_1280x1024: 263 *out_space = B_RGB15; 264 *width = 1280; *height = 1024; 265 break; 266 case B_15_BIT_1600x1200: 267 *out_space = B_RGB15; 268 *width = 1600; *height = 1200; 269 break; 270 case B_15_BIT_1152x900: 271 *out_space = B_RGB15; 272 *width = 1152; *height = 900; 273 break; 274 } 275 } 276 277 278 // BWindowScreen public API 279 280 void 281 set_mouse_position(int32 x, int32 y) 282 { 283 BMessage command(WS_SET_MOUSE_POSITION); 284 BMessage reply; 285 286 command.AddPoint("where", BPoint(x, y)); 287 _control_input_server_(&command, &reply); 288 } 289 290 291 BWindowScreen::BWindowScreen(const char *title, uint32 space, status_t *error, bool debug_enable) 292 : 293 BWindow(BScreen().Frame(), title, B_TITLED_WINDOW, 294 WS_SPECIAL_FLAG | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE, 295 B_CURRENT_WORKSPACE) 296 { 297 CALLED(); 298 uint32 attributes = 0; 299 if (debug_enable) 300 attributes |= B_ENABLE_DEBUGGER; 301 302 *error = InitData(space, attributes); 303 } 304 305 306 BWindowScreen::BWindowScreen(const char *title, uint32 space, uint32 attributes, status_t *error) 307 : 308 BWindow(BScreen().Frame(), title, B_TITLED_WINDOW, 309 WS_SPECIAL_FLAG | B_NOT_MINIMIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE, 310 B_CURRENT_WORKSPACE) 311 { 312 CALLED(); 313 *error = InitData(space, attributes); 314 } 315 316 317 BWindowScreen::~BWindowScreen() 318 { 319 Disconnect(); 320 if (addon_state == 1) 321 unload_add_on(addon_image); 322 323 SetFullscreen(0); 324 325 delete_sem(activate_sem); 326 delete_sem(debug_sem); 327 328 if (debug_state) { 329 _BAppServerLink_ link; 330 link.fSession->swrite_l(WS_SWITCH_WORKSPACE); 331 link.fSession->swrite_l(debug_workspace); 332 link.fSession->sync(); 333 } 334 335 free(new_space); 336 free(old_space); 337 free(mode_list); 338 } 339 340 341 void 342 BWindowScreen::Quit(void) 343 { 344 Disconnect(); 345 BWindow::Quit(); 346 } 347 348 349 void 350 BWindowScreen::ScreenConnected(bool active) 351 { 352 // Implemented in subclasses 353 } 354 355 356 void 357 BWindowScreen::Disconnect() 358 { 359 if (lock_state == 1) { 360 if (debug_state) 361 debug_first = true; 362 SetActiveState(0); 363 } 364 } 365 366 void 367 BWindowScreen::WindowActivated(bool active) 368 { 369 window_state = active; 370 if(active && lock_state == 0 && work_state) 371 SetActiveState(1); 372 } 373 374 void 375 BWindowScreen::WorkspaceActivated(int32 ws, 376 bool state) 377 { 378 work_state = state; 379 if (state) { 380 if (lock_state == 0 && window_state) { 381 SetActiveState(1); 382 if (!IsHidden()) { 383 Activate(true); 384 WindowActivated(true); 385 } 386 } 387 } else { 388 if (lock_state) 389 SetActiveState(0); 390 } 391 } 392 393 394 void 395 BWindowScreen::ScreenChanged(BRect screen_size, color_space depth) 396 { 397 // Implemented in subclasses 398 } 399 400 401 void 402 BWindowScreen::Hide() 403 { 404 if (lock_state == 1) { 405 if (debug_state) 406 debug_first = true; 407 SetActiveState(0); 408 } 409 410 BWindow::Hide(); 411 } 412 413 414 void 415 BWindowScreen::Show() 416 { 417 BWindow::Show(); 418 if (!activate_state) { 419 release_sem(activate_sem); 420 activate_state = true; 421 } 422 } 423 424 425 void 426 BWindowScreen::SetColorList(rgb_color *list, int32 first_index, int32 last_index) 427 { 428 if (first_index < 0 || last_index > 255 || first_index > last_index) 429 return; 430 431 if (Lock()) { 432 if (!activate_state) { 433 //If we aren't active, we just change our local palette 434 for (int32 x = first_index; x <= last_index; x++) 435 colorList[x] = list[x]; 436 } else { 437 uint32 colorCount = last_index - first_index + 1; 438 if (addon_state == 1) { 439 set_indexed_colors sic = (set_indexed_colors)m_gah(B_SET_INDEXED_COLORS, NULL); 440 if (sic != NULL) 441 sic(colorCount, first_index, (uint8*)colorList, 0); 442 } 443 444 BScreen screen(this); 445 screen.WaitForRetrace(); 446 // Update our local palette too. We're doing this between two 447 // WaitForRetrace() calls so nobody will notice. 448 for (int32 x = first_index; x <= last_index; x++) 449 colorList[x] = list[x]; 450 451 // Tell the app_server about our changes 452 _BAppServerLink_ link; 453 link.fSession->swrite_l(WS_SET_PALETTE); 454 link.fSession->swrite_l(screen_index); 455 link.fSession->swrite_l(first_index); 456 link.fSession->swrite_l(last_index); 457 link.fSession->swrite(colorCount * sizeof(rgb_color), colorList); 458 link.fSession->sync(); 459 460 screen.WaitForRetrace(); 461 } 462 463 Unlock(); 464 } 465 } 466 467 468 status_t 469 BWindowScreen::SetSpace(uint32 space) 470 { 471 display_mode mode; 472 status_t status = GetModeFromSpace(space, &mode); 473 if (status == B_OK) 474 status = AssertDisplayMode(&mode); 475 return status; 476 } 477 478 479 bool 480 BWindowScreen::CanControlFrameBuffer() 481 { 482 bool retval = false; 483 if (addon_state <= 1 && (card_info.flags & B_FRAME_BUFFER_CONTROL)) 484 retval = true; 485 486 return retval; 487 } 488 489 490 status_t 491 BWindowScreen::SetFrameBuffer(int32 width, int32 height) 492 { 493 display_mode highMode = *new_space; 494 495 highMode.virtual_height = (int16)height; 496 highMode.virtual_width = (int16)width; 497 498 display_mode lowMode = highMode; 499 display_mode mode = highMode; 500 501 // equivalent to BScreen::ProposeMode() 502 _BAppServerLink_ link; 503 link.fSession->swrite_l(WS_DISPLAY_UTILS); 504 link.fSession->swrite_l(screen_index); 505 link.fSession->swrite_l(WS_PROPOSE_MODE); 506 link.fSession->swrite(sizeof(display_mode), &highMode); 507 link.fSession->swrite(sizeof(display_mode), &mode); 508 link.fSession->swrite(sizeof(display_mode), &lowMode); 509 link.fSession->sync(); 510 511 status_t status; 512 link.fSession->sread(sizeof(status), &status); 513 link.fSession->sread(sizeof(display_mode), &mode); 514 515 // If the mode is supported, change the workspace 516 // to that mode. 517 if (status == B_OK) 518 status = AssertDisplayMode(&mode); 519 520 return status; 521 } 522 523 524 status_t 525 BWindowScreen::MoveDisplayArea(int32 x, int32 y) 526 { 527 _BAppServerLink_ link; 528 link.fSession->swrite_l(WS_DISPLAY_UTILS); 529 link.fSession->swrite_l(screen_index); 530 link.fSession->swrite_l(WS_MOVE_DISPLAY); 531 link.fSession->swrite(sizeof(int16), (int16*)&x); 532 link.fSession->swrite(sizeof(int16), (int16*)&y); 533 link.fSession->sync(); 534 535 status_t status; 536 link.fSession->sread(sizeof(status), &status); 537 538 if (status == B_OK) { 539 format_info.display_x = x; 540 format_info.display_y = y; 541 new_space->h_display_start = x; 542 new_space->v_display_start = y; 543 } 544 return status; 545 } 546 547 548 void * 549 BWindowScreen::IOBase() 550 { 551 // Not supported 552 return NULL; 553 } 554 555 556 rgb_color * 557 BWindowScreen::ColorList() 558 { 559 return colorList; 560 } 561 562 563 frame_buffer_info * 564 BWindowScreen::FrameBufferInfo() 565 { 566 return &format_info; 567 } 568 569 570 graphics_card_hook 571 BWindowScreen::CardHookAt(int32 index) 572 { 573 if (addon_state != 1) 574 return 0; 575 576 graphics_card_hook hook = NULL; 577 578 switch (index) { 579 case 5: // 8 bit fill rect 580 hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0); 581 fill_rect = (fill_rectangle)hook; 582 fill_rect_global = fill_rect; 583 hook = (graphics_card_hook)draw_rect_8; 584 break; 585 case 6: // 32 bit fill rect 586 hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0); 587 fill_rect = (fill_rectangle)hook; 588 fill_rect_global = fill_rect; 589 hook = (graphics_card_hook)draw_rect_32; 590 break; 591 case 7: // screen to screen blit 592 hook = (graphics_card_hook)m_gah(B_SCREEN_TO_SCREEN_BLIT, 0); 593 blit_rect = (screen_to_screen_blit)hook; 594 blit_rect_global = blit_rect; 595 hook = (graphics_card_hook)blit; 596 break; 597 case 8: // screen to screen scaled filtered blit 598 hook = (graphics_card_hook)m_gah(B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT, 0); 599 scaled_filtered_blit_rect = (screen_to_screen_scaled_filtered_blit)hook; 600 scaled_filtered_blit_rect_global = scaled_filtered_blit_rect; 601 hook = (graphics_card_hook)scaled_filtered_blit; 602 break; 603 case 10: // sync aka wait for graphics card idle 604 hook = (graphics_card_hook)sync; 605 break; 606 case 13: // 16 bit fill rect 607 hook = (graphics_card_hook)m_gah(B_FILL_RECTANGLE, 0); 608 fill_rect = (fill_rectangle)hook; 609 fill_rect_global = fill_rect; 610 hook = (graphics_card_hook)draw_rect_16; 611 break; 612 default: 613 break; 614 } 615 616 return hook; 617 } 618 619 620 graphics_card_info * 621 BWindowScreen::CardInfo() 622 { 623 return &card_info; 624 } 625 626 627 void 628 BWindowScreen::RegisterThread(thread_id id) 629 { 630 CALLED(); 631 while (acquire_sem(debug_sem) == B_INTERRUPTED) 632 ; 633 ++debug_list_count; 634 debug_list = (thread_id *)realloc(debug_list, debug_list_count * sizeof(thread_id)); 635 debug_list[debug_list_count - 1] = id; 636 637 release_sem(debug_sem); 638 } 639 640 641 void 642 BWindowScreen::SuspensionHook(bool active) 643 { 644 // Implemented in subclasses 645 } 646 647 648 void 649 BWindowScreen::Suspend(char *label) 650 { 651 CALLED(); 652 if (debug_state) { 653 fprintf(stderr, "## Debugger(\"%s\").", label); 654 fprintf(stderr, " Press Alt-F%ld or Cmd-F%ld to resume.\n", space0 + 1, space0 + 1); 655 656 if (IsLocked()) 657 Unlock(); 658 659 // Switch to debug workspace 660 _BAppServerLink_ link; 661 link.fSession->swrite_l(WS_SWITCH_WORKSPACE); 662 link.fSession->swrite_l(debug_workspace); 663 link.fSession->sync(); 664 665 // Suspend ourself 666 suspend_thread(find_thread(NULL)); 667 668 Lock(); 669 } 670 } 671 672 673 status_t 674 BWindowScreen::Perform(perform_code d, 675 void *arg) 676 { 677 return inherited::Perform(d, arg); 678 } 679 680 681 void 682 BWindowScreen::_ReservedWindowScreen1() 683 { 684 } 685 686 687 void 688 BWindowScreen::_ReservedWindowScreen2() 689 { 690 } 691 692 693 void 694 BWindowScreen::_ReservedWindowScreen3() 695 { 696 } 697 698 699 void 700 BWindowScreen::_ReservedWindowScreen4() 701 { 702 } 703 704 705 /* unimplemented for protection of the user: 706 * 707 * BWindowScreen::BWindowScreen() 708 * BWindowScreen::BWindowScreen(BWindowScreen &) 709 * BWindowScreen &BWindowScreen::operator=(BWindowScreen &) 710 */ 711 712 713 BRect 714 BWindowScreen::CalcFrame(int32 index, int32 space, display_mode *dmode) 715 { 716 BScreen screen; 717 if (dmode) 718 screen.GetMode(dmode); 719 720 return screen.Frame(); 721 } 722 723 724 int32 725 BWindowScreen::SetFullscreen(int32 enable) 726 { 727 a_session->swrite_l(WS_SET_FULLSCREEN); 728 a_session->swrite_l(server_token); 729 a_session->swrite_l(enable); 730 a_session->sync(); 731 732 int32 result, retval; 733 734 a_session->sread(sizeof(result), &result); 735 a_session->sread(sizeof(retval), &retval); 736 737 return retval; 738 } 739 740 status_t 741 BWindowScreen::InitData(uint32 space, uint32 attributes) 742 { 743 BScreen screen(this); 744 debug_state = attributes & B_ENABLE_DEBUGGER; 745 debug_list_count = 0; 746 debug_list = 0; 747 debug_first = true; 748 749 debug_sem = create_sem(1, "WindowScreen debug sem"); 750 old_space = (display_mode *)calloc(0x1, sizeof(display_mode)); 751 new_space = (display_mode *)calloc(0x1, sizeof(display_mode)); 752 753 screen.GetModeList(&mode_list, &mode_count); 754 755 _attributes = attributes; 756 757 display_mode *n_space = new_space; 758 screen_index = 0; 759 lock_state = 0; 760 addon_state = 0; 761 direct_enable = 0; 762 window_state = 0; 763 764 space_mode = 1; 765 766 GetModeFromSpace(space, n_space); 767 768 space0 = 0; 769 770 SetWorkspaces(B_CURRENT_WORKSPACE); 771 772 SetFullscreen(1); 773 work_state = 1; 774 debug_workspace = 0; 775 const color_map *map = screen.ColorMap(); 776 memcpy(colorList, map->color_list, 256); 777 778 GetCardInfo(); 779 activate_sem = create_sem(0, "WindowScreen start lock"); 780 activate_state = 0; 781 782 783 return B_OK; 784 } 785 786 787 status_t 788 BWindowScreen::SetActiveState(int32 state) 789 { 790 status_t status = B_ERROR; 791 if (state == 1) { 792 be_app->HideCursor(); 793 if (be_app->IsCursorHidden() 794 && (status = SetLockState(1)) == B_OK) { 795 status = AssertDisplayMode(new_space); 796 if (status == B_OK) { 797 if (!activate_state) { 798 while (acquire_sem(activate_sem) == B_INTERRUPTED) 799 ; 800 } 801 SetColorList(colorList); 802 if (debug_state && !debug_first) { 803 SuspensionHook(true); 804 Resume(); 805 } else { 806 debug_first = true; 807 ScreenConnected(true); 808 } 809 if (status == B_OK) 810 return status; 811 812 } else 813 SetLockState(0); 814 815 be_app->ShowCursor(); 816 } 817 } else { 818 if (debug_state && !debug_first) { 819 Suspend(); 820 SuspensionHook(false); 821 } else 822 ScreenConnected(false); 823 824 status = SetLockState(0); 825 if (status == B_OK) { 826 be_app->ShowCursor(); 827 if (activate_state) { 828 _BAppServerLink_ link; 829 link.fSession->swrite_l(0xF27); 830 link.fSession->swrite_l(screen_index); 831 link.fSession->swrite_l(0); 832 link.fSession->swrite_l(255); 833 const color_map *colorMap = system_colors(); 834 link.fSession->swrite(256 * sizeof(rgb_color), const_cast<rgb_color *>(colorMap->color_list)); 835 link.fSession->sync(); 836 } 837 } 838 } 839 return status; 840 } 841 842 status_t 843 BWindowScreen::SetLockState(int32 state) 844 { 845 if(addon_state == 1 && state == 1) { 846 m_wei(); 847 fill_rect_global = NULL; 848 blit_rect_global = NULL; 849 trans_blit_rect_global = NULL; 850 scaled_filtered_blit_rect_global = NULL; 851 wait_idle_global = NULL; 852 et_global = NULL; 853 acquire_engine_global = NULL; 854 release_engine_global = NULL; 855 } 856 857 _BAppServerLink_ link; 858 link.fSession->swrite_l(0x00000efb); 859 link.fSession->swrite_l(screen_index); 860 link.fSession->swrite_l(state); 861 link.fSession->swrite_l(server_token); 862 link.fSession->sync(); 863 864 status_t status; 865 link.fSession->sread(sizeof(status), &status); 866 867 if (status == B_NO_ERROR) { 868 lock_state = state; 869 if (state == 1) { 870 if (addon_state == 0) { 871 status = InitClone(); 872 873 if (status == B_OK) { 874 addon_state = 1; 875 m_wei = (wait_engine_idle)m_gah(B_WAIT_ENGINE_IDLE, NULL); 876 m_re = (release_engine)m_gah(B_RELEASE_ENGINE, NULL); 877 m_ae = (acquire_engine)m_gah(B_ACQUIRE_ENGINE, NULL); 878 } else 879 addon_state = -1; 880 } 881 882 if (addon_state == 1 && state == 1) { 883 fill_rect_global = fill_rect; 884 blit_rect_global = blit_rect; 885 trans_blit_rect_global = trans_blit_rect; 886 scaled_filtered_blit_rect_global = scaled_filtered_blit_rect; 887 wait_idle_global = m_wei; 888 et_global = et; 889 acquire_engine_global = m_ae; 890 release_engine_global = m_re; 891 m_wei(); 892 } 893 } 894 } 895 896 return status; 897 } 898 899 900 void 901 BWindowScreen::GetCardInfo() 902 { 903 BScreen screen(this); 904 frame_buffer_config config; 905 906 display_mode mode; 907 uint32 bits_per_pixel; 908 909 card_info.version = 2; 910 card_info.id = 0; 911 screen.GetMode(&mode); 912 913 switch(mode.space & 0x0fff) { 914 case B_CMAP8: 915 bits_per_pixel = 8; 916 break; 917 case B_RGB16: 918 bits_per_pixel = 16; 919 break; 920 case B_RGB32: 921 bits_per_pixel = 32; 922 break; 923 default: 924 bits_per_pixel = 0; 925 break; 926 } 927 card_info.bits_per_pixel = bits_per_pixel; 928 card_info.width = mode.virtual_width; 929 card_info.height = mode.virtual_height; 930 931 if (mode.space & 0x10) 932 strncpy(card_info.rgba_order, "rgba", 4); 933 else 934 strncpy(card_info.rgba_order, "bgra", 4); 935 936 card_info.flags = 0; 937 938 if (mode.flags & B_SCROLL) 939 card_info.flags = B_FRAME_BUFFER_CONTROL; 940 if (mode.flags & B_PARALLEL_ACCESS) 941 card_info.flags |= B_PARALLEL_BUFFER_ACCESS; 942 943 screen_id id = screen.ID(); 944 _BAppServerLink_ link; 945 link.fSession->swrite_l(WS_GET_FRAMEBUFFER); 946 link.fSession->swrite_l(id.id); 947 link.fSession->sync(); 948 949 int32 result; 950 link.fSession->sread(sizeof(result), &result); 951 952 if(result == B_NO_ERROR) { 953 link.fSession->sread(sizeof(frame_buffer_config), &config); 954 card_info.id = id.id; 955 card_info.frame_buffer = config.frame_buffer; 956 card_info.bytes_per_row = config.bytes_per_row; 957 } 958 memcpy(&card_info_global, &card_info, sizeof(graphics_card_info)); 959 } 960 961 962 void 963 BWindowScreen::Suspend() 964 { 965 CALLED(); 966 967 while (acquire_sem(debug_sem) == B_INTERRUPTED) 968 ; 969 970 // Suspend all the registered threads 971 for (int i = 0; i < debug_list_count; i++) { 972 snooze(10000); 973 suspend_thread(debug_list[i]); 974 } 975 976 graphics_card_info *info = CardInfo(); 977 size_t fbSize = info->bytes_per_row * info->height; 978 979 // Save the content of the frame buffer into the local buffer 980 debug_buffer = (char *)malloc(fbSize); 981 memcpy(debug_buffer, info->frame_buffer, fbSize); 982 } 983 984 985 void 986 BWindowScreen::Resume() 987 { 988 CALLED(); 989 graphics_card_info *info = CardInfo(); 990 991 // Copy the content of the debug_buffer back into the frame buffer. 992 memcpy(info->frame_buffer, debug_buffer, info->bytes_per_row * info->height); 993 free(debug_buffer); 994 995 // Resume all the registered threads 996 for (int i = 0; i < debug_list_count; i++) 997 resume_thread(debug_list[i]); 998 999 release_sem(debug_sem); 1000 } 1001 1002 1003 status_t 1004 BWindowScreen::GetModeFromSpace(uint32 space, display_mode *dmode) 1005 { 1006 uint32 out_space; 1007 int32 width, height; 1008 status_t ret = B_ERROR; 1009 1010 mode2parms(space, &out_space, &width, &height); 1011 // mode2parms converts the space to actual width, height and color_space, e.g B_8_BIT_640x480 1012 1013 for (uint32 i = 0; i < mode_count; i++) { 1014 if (mode_list[i].space == out_space && mode_list[i].virtual_width == width 1015 && mode_list[i].virtual_height == height) { 1016 1017 memcpy(dmode, &mode_list[i], sizeof(display_mode)); 1018 ret = B_OK; 1019 break; 1020 } 1021 } 1022 1023 return ret; 1024 } 1025 1026 1027 status_t 1028 BWindowScreen::InitClone() 1029 { 1030 _BAppServerLink_ link; 1031 link.fSession->swrite_l(WS_GET_ACCELERANT_NAME); 1032 link.fSession->swrite_l(screen_index); 1033 link.fSession->sync(); 1034 1035 int32 result; 1036 link.fSession->sread(sizeof(result), &result); 1037 if (result != B_OK) 1038 return result; 1039 1040 link.fSession->sread(sizeof(result), &result); // read length of accelerant's name 1041 1042 char *addonName = (char *)malloc((result + 1) * sizeof (char)); 1043 link.fSession->sread(result, addonName); // read the accelerant's name 1044 addonName[result] = '\0'; 1045 1046 link.fSession->swrite_l(WS_GET_DRIVER_NAME); // get driver's name without the /dev/ 1047 link.fSession->swrite_l(screen_index); 1048 link.fSession->sync(); 1049 1050 link.fSession->sread(sizeof(result), &result); 1051 if (result != B_OK) 1052 return result; 1053 1054 link.fSession->sread(sizeof(result), &result); 1055 // result now contains the length of the buffer needed for the drivers path name 1056 1057 char *path = (char *)malloc((result + 1) * sizeof(char)); 1058 link.fSession->sread(result, path); 1059 path[result] = '\0'; 1060 // path now contains the driver's name 1061 1062 // load the accelerant 1063 addon_image = load_add_on(addonName); 1064 1065 free(addonName); 1066 1067 if(addon_image < 0) 1068 return B_ERROR; 1069 1070 // now get the symbol for GetAccelerantHook m_gah 1071 if (get_image_symbol(addon_image, "get_accelerant_hook", 1072 B_SYMBOL_TYPE_ANY, (void **)&m_gah) < 0) 1073 return B_ERROR; 1074 1075 // now use m_gah to get a pointer to the accelerant's clone accelerant 1076 clone_accelerant clone = (clone_accelerant)m_gah(B_CLONE_ACCELERANT, 0); 1077 1078 if (!clone) 1079 return B_ERROR; 1080 1081 // test if the driver supports cloning of the accelerant, using the path we got earlier 1082 result = clone((void *)path); 1083 free(path); 1084 1085 if (result != 0) { 1086 unload_add_on(addon_image); 1087 addon_image = -1; 1088 } 1089 1090 return result; 1091 } 1092 1093 1094 status_t 1095 BWindowScreen::AssertDisplayMode(display_mode *dmode) 1096 { 1097 status_t result; 1098 _BAppServerLink_ link; 1099 1100 link.fSession->swrite_l(WS_GET_DISPLAY_MODE); // check display_mode valid command 1101 link.fSession->swrite_l(screen_index); 1102 link.fSession->swrite(sizeof(display_mode), (void *)dmode); 1103 link.fSession->sync(); 1104 1105 link.fSession->sread(sizeof(result), &result); 1106 1107 // if the result is B_OK, we copy the dmode to new_space 1108 if (result == B_OK) { 1109 memcpy(new_space, dmode, sizeof(display_mode)); 1110 space_mode = 1; 1111 } 1112 GetCardInfo(); 1113 1114 format_info.bits_per_pixel = card_info.bits_per_pixel; 1115 format_info.bytes_per_row = card_info.bytes_per_row; 1116 format_info.width = card_info.width; 1117 format_info.height = card_info.height; 1118 format_info.display_width = card_info.width; 1119 format_info.display_height = card_info.height; 1120 format_info.display_x = 0; 1121 format_info.display_y = 0; 1122 1123 return result; 1124 } 1125