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