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