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