📄 multimon.c
字号:
/* Copyright (c) 2002, Thomas Kurschel Part of Radeon accelerant Multi-monitor management*/#include "radeon_accelerant.h"#include "generic.h"#include "GlobalData.h"// transform official mode to internal, multi-screen mode enhanced modevoid Radeon_DetectMultiMode( virtual_card *vc, display_mode *mode ){ (void)vc; mode->timing.flags &= ~RADEON_MODE_MASK; // combine mode is used if virtual area is twice as visible area // and if scrolling is enabled; if combining is impossible, use // cloning instead if( (mode->flags & B_SCROLL) == 0 ) return; SHOW_FLOW0( 3, "possibly combine mode" ); // remove scroll flag - we don't need it anymore mode->flags &= ~B_SCROLL; mode->timing.flags &= ~RADEON_MODE_POSITION_MASK; if( mode->virtual_width == 2 * mode->timing.h_display ) { SHOW_FLOW0( 2, "horizontal combine mode" ); mode->timing.flags |= RADEON_MODE_POSITION_HORIZONTAL; mode->timing.flags &= ~RADEON_MODE_MASK; mode->timing.flags |= RADEON_MODE_COMBINE; } else if( mode->virtual_height == 2 * mode->timing.v_display ) { SHOW_FLOW0( 2, "vertical combine mode" ); mode->timing.flags |= RADEON_MODE_POSITION_VERTICAL; mode->timing.flags &= ~RADEON_MODE_MASK; mode->timing.flags |= RADEON_MODE_COMBINE; } else { // ups, this isn't really a combine mode - restore flags SHOW_FLOW0( 2, "wasn't really a combine mode" ); mode->timing.flags &= ~RADEON_MODE_MASK; mode->flags |= B_SCROLL; }}// make sure selected multi-screen mode is valid; adapt it if neededvoid Radeon_VerifyMultiMode( virtual_card *vc, shared_info *si, display_mode *mode ){ // if there is no second port or no second monitor connected, // fall back to standard mode int num_usable_crtcs = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none; if( si->num_crtc > 1 ) num_usable_crtcs += vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none; if( num_usable_crtcs < 2 ) { SHOW_FLOW0( 2, "only one monitor - disabling any multi-mon mode" ); // restore flags if combine mode is selected if( (mode->timing.flags & RADEON_MODE_MASK) == RADEON_MODE_COMBINE ) mode->flags |= B_SCROLL; mode->timing.flags &= ~RADEON_MODE_MASK; mode->timing.flags |= RADEON_MODE_STANDARD; }}// transform internal, multi-screen enabled display mode// to official modevoid Radeon_HideMultiMode( virtual_card *vc, display_mode *mode ){ (void) vc; // restore flags for combine mode if( (mode->timing.flags & RADEON_MODE_MASK) == RADEON_MODE_COMBINE ) mode->flags |= B_SCROLL;}// initialize multi-screen mode dependant variablesvoid Radeon_InitMultiModeVars( accelerator_info *ai, display_mode *mode ){ virtual_card *vc = ai->vc; shared_info *si = ai->si; uint32 x, y; // setup single-screen mode vc->eff_width = mode->timing.h_display; vc->eff_height = mode->timing.v_display; if( vc->used_crtc[0] ) { si->crtc[0].rel_x = 0; si->crtc[0].rel_y = 0; } if( vc->used_crtc[1] ) { si->crtc[1].rel_x = 0; si->crtc[1].rel_y = 0; } switch( mode->timing.flags & RADEON_MODE_MASK ) { case RADEON_MODE_COMBINE: // detect where second screen must be located and // adapt total visible area accordingly if( (mode->timing.flags & RADEON_MODE_POSITION_MASK) == RADEON_MODE_POSITION_HORIZONTAL ) { vc->eff_width = 2 * mode->timing.h_display; x = mode->timing.h_display; y = 0; } else { vc->eff_height = 2 * mode->timing.v_display; x = 0; y = mode->timing.v_display; } SHOW_FLOW( 3, "relative position of second screen: %d, %d", x, y ); // set relative offset if( !vc->swap_displays ) { si->crtc[1].rel_x = x; si->crtc[1].rel_y = y; } else { si->crtc[0].rel_x = x; si->crtc[0].rel_y = y; } break; default: // else, ports are independant but show the same break; }}// mapping of internal TV standard code to public TV standard codestatic const uint32 private2be[] = { 0, 1, 3, 4, 103, 3/* PAL SCART - no public id, so I use PAL BDGHI */, 102 };// check and execute tunnel settings commandstatus_t Radeon_CheckMultiMonTunnel( virtual_card *vc, display_mode *mode, const display_mode *low, const display_mode *high, bool *isTunneled ){ if( (mode->timing.flags & RADEON_MODE_MULTIMON_REQUEST) != 0 && (mode->timing.flags & RADEON_MODE_MULTIMON_REPLY) == 0 ) { mode->timing.flags &= ~RADEON_MODE_MULTIMON_REQUEST; mode->timing.flags |= RADEON_MODE_MULTIMON_REPLY; // still process request, just in case someone set this flag // combination by mistake // TBD: disabled to shorten syslog *isTunneled = true; return B_OK; } // check magic params if( mode->space != 0 || low->space != 0 || high->space != 0 || low->virtual_width != 0xffff || low->virtual_height != 0xffff || high->virtual_width != 0 || high->virtual_height != 0 || mode->timing.pixel_clock != 0 || low->timing.pixel_clock != 'TKTK' || high->timing.pixel_clock != 'KTKT' ) { *isTunneled = false; return B_OK; } *isTunneled = true; /*SHOW_FLOW( 1, "tunnel access code=%d, command=%d", mode->h_display_start, mode->v_display_start );*/ switch( mode->h_display_start ) { case ms_swap: switch( mode->v_display_start ) { case 0: mode->timing.flags = vc->swap_displays; return B_OK; case 1: vc->swap_displays = mode->timing.flags != 0; vc->enforce_mode_change = true; // write settings instantly Radeon_WriteSettings( vc ); return B_OK; } break; case ms_use_laptop_panel: // we must refuse this setting if there is no laptop panel; // else, the preferences dialog would show this (useless) option if( (vc->connected_displays & dd_lvds) == 0 ) return B_ERROR; switch( mode->v_display_start ) { case 0: mode->timing.flags = vc->use_laptop_panel; //SHOW_FLOW( 1, "get use_laptop_panel settings (%d)", mode->timing.flags ); return B_OK; case 1: vc->use_laptop_panel = mode->timing.flags != 0; //SHOW_FLOW( 1, "set use_laptop_panel settings (%d)", vc->use_laptop_panel ); vc->enforce_mode_change = true; Radeon_WriteSettings( vc ); return B_OK; } break; case ms_tv_standard: switch( mode->v_display_start ) { case 0: mode->timing.flags = private2be[vc->tv_standard]; /*SHOW_FLOW( 1, "read tv_standard (internal %d, public %d)", vc->tv_standard, mode->timing.flags );*/ return B_OK; case 1: switch( mode->timing.flags ) { case 0: vc->tv_standard = ts_off; break; case 1: vc->tv_standard = ts_ntsc; break; case 2: break; // ntsc j case 3: vc->tv_standard = ts_pal_bdghi; break; case 4: vc->tv_standard = ts_pal_m; break; case 5: break; // pal n case 6: break; // secam - I reckon not supported by hardware case 101: break; // ntsc 443 case 102: vc->tv_standard = ts_pal_60; break; case 103: vc->tv_standard = ts_pal_nc; break; } SHOW_FLOW( 1, "set tv_standard (internal %d, public %d)", vc->tv_standard, mode->timing.flags ); vc->enforce_mode_change = true; Radeon_WriteSettings( vc ); return B_OK; case 2: { uint32 idx = mode->timing.flags; // we limit it explicetely to NTSC and PAL as all other // modes are not fully implemented if( idx < sizeof( private2be ) / sizeof( private2be[0] ) && idx < 3 ) { mode->timing.flags = private2be[idx]; return B_OK; } else return B_ERROR; } } } return B_ERROR;}// return true if both ports must be programmedbool Radeon_NeedsSecondPort( display_mode *mode ){ switch( mode->timing.flags & RADEON_MODE_MASK ) { case RADEON_MODE_COMBINE: return true; default: return false; }}// return number of ports showing differents parts of frame bufferbool Radeon_DifferentPorts( display_mode *mode ){ switch( mode->timing.flags & RADEON_MODE_MASK ) { case RADEON_MODE_COMBINE: return 2; default: return 1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -