VGA Switcheroo¶
vga_switcheroo是Linux用于笔记本电脑混合显卡的子系统。这些显卡有两种类型
复用型:具有双GPU和一个复用器芯片,用于在GPU之间切换输出。
非复用型:具有双GPU,但只有一个连接到输出。另一个仅用于分担渲染任务,其结果通过PCIe复制到帧缓冲区中。在Linux上,这通过DRI PRIME支持。
混合显卡在2000年代后期开始出现,最初都是复用型的。较新的笔记本电脑出于成本原因转向非复用架构。一个值得注意的例外是MacBook Pro,它继续使用复用器。复用器具有不同的功能:有些仅切换面板,有些还可以切换外部显示器。有些一次切换所有显示引脚,而另一些只能切换DDC线路。(允许探测非活动GPU的EDID。)此外,复用器通常用于在未使用独立GPU时切断其电源。
DRM驱动程序向vga_switcheroo注册GPU,这些GPU此后被称为客户端。复用器被称为处理程序。非复用机器也注册一个处理程序来控制独立GPU的电源状态,其->switchto回调由于显而易见的原因是一个空操作。独立GPU通常配备用于HDMI/DP音频信号的HDA控制器,它也将注册为客户端,以便vga_switcheroo可以在更改独立GPU的电源状态时处理正确的挂起/恢复顺序。总共有最多三个客户端:两个vga客户端(GPU)和一个音频客户端(在独立GPU上)。代码主要准备好支持具有两个以上GPU的机器,如果它们可用的话。
当前输出切换到的GPU在vga_switcheroo术语中称为活动客户端。未使用的GPU是非活动客户端。当非活动客户端的DRM驱动程序加载时,它将无法探测面板的EDID,因此依赖于VBIOS来提供其显示模式。如果VBIOS模式是错误的,或者根本没有VBIOS(这在MacBook Pro上很常见),则客户端可以替代地请求将DDC线路临时切换到它,前提是处理程序支持此操作。仅切换DDC线路而不切换整个输出可以避免不必要的闪烁。
使用模式¶
手动切换和手动电源控制¶
在这种使用模式下,可以读取文件/sys/kernel/debug/vgaswitcheroo/switch以检索当前的vga_switcheroo状态,并且可以向其写入命令以更改状态。一旦两个GPU驱动程序和一个处理程序已向vga_switcheroo注册,该文件就会出现。理解以下命令
OFF:关闭未使用的设备的电源。
ON:打开未使用的设备的电源。
IGD:切换到集成显卡设备。如有必要,打开集成GPU的电源,关闭独立GPU的电源。前提是没有用户空间进程(例如Xorg,alsactl)已打开GPU或音频设备的设备文件。如果切换失败,用户可以在/dev/dri/和/dev/snd/controlC1上调用lsof(8)或fuser(1)以识别阻止切换的进程。
DIS:切换到独立显卡设备。
DIGD:延迟切换到集成显卡设备。一旦最后一个用户空间进程关闭GPU和音频设备的设备文件,这将执行切换。
DDIS:延迟切换到独立显卡设备。
MIGD:仅复用器切换到集成显卡设备。不重新映射控制台或更改任一gpu的电源状态。如果当前关闭集成GPU,屏幕将变黑。如果已打开,屏幕将显示VRAM中发生的任何事情。无论哪种方式,用户都必须盲目地输入命令才能切换回来。
MDIS:仅复用器切换到独立显卡设备。
对于其电源状态由驱动程序的运行时pm控制的GPU,ON和OFF命令是空操作(请参见下一节)。
对于非复用机器,不应使用IGD/DIS,DIGD/DDIS和MIGD/MDIS命令。
驱动程序电源控制¶
在这种使用模式下,独立GPU会自动打开和关闭电源,由驱动程序的运行时pm决定。在复用机器上,用户仍然可以通过debugfs接口影响复用器的状态,但是ON和OFF命令对于独立GPU变为空操作。
此模式是Nvidia HybridPower/Optimus和ATI PowerXpress上的默认模式。在内核命令行上指定nouveau.runpm=0,radeon.runpm=0或amdgpu.runpm=0会禁用它。
在GPU挂起后,需要调用处理程序以切断GPU的电源。同样,在GPU可以恢复之前,需要恢复电源。这是通过vga_switcheroo_init_domain_pm_ops()
实现的,它通过对处理程序的必要调用来扩充GPU的挂起/恢复功能。
当音频设备恢复时,需要唤醒GPU。这是通过一个PCI quirk实现的,该quirk调用device_link_add()
来声明对GPU的依赖性。这样,只要音频设备正在使用,GPU就会保持唤醒状态。
在复用机器上,如果复用器最初切换到独立GPU,则用户最终会在启动后GPU断电时得到黑屏。作为一种解决方法,在运行时挂起时,复用器被迫切换到集成GPU,请参见https://bugs.freedesktop.org/show_bug.cgi?id=75917
API¶
公共函数¶
-
int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, enum vga_switcheroo_handler_flags_t handler_flags)¶
注册处理程序
参数
const struct vga_switcheroo_handler *handler
处理程序回调
enum vga_switcheroo_handler_flags_t handler_flags
处理程序标志
描述
注册处理程序。如果两个vga客户端已经注册,则启用vga_switcheroo。
返回值
成功时返回0,如果已注册处理程序,则返回-EINVAL。
-
void vga_switcheroo_unregister_handler(void)¶
注销处理程序
参数
void
无参数
描述
注销处理程序。禁用vga_switcheroo。
-
enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void)¶
获取处理程序标志
参数
void
无参数
描述
客户端获取处理程序标志位掩码的助手函数。
返回值
处理程序标志。值为0表示未注册处理程序或处理程序没有特殊功能。
-
int vga_switcheroo_register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control)¶
注册vga客户端
参数
struct pci_dev *pdev
客户端pci设备
const struct vga_switcheroo_client_ops *ops
客户端回调
bool driver_power_control
电源状态是否由驱动程序的运行时pm控制
描述
注册vga客户端(GPU)。如果另一个GPU和一个处理程序已注册,则启用vga_switcheroo。客户端的电源状态假定为ON。在此之前,应调用vga_switcheroo_client_probe_defer()
以确保满足所有前提条件。
返回值
成功时返回0,内存分配错误时返回-ENOMEM。
-
int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, struct pci_dev *vga_dev)¶
注册音频客户端
参数
struct pci_dev *pdev
客户端pci设备
const struct vga_switcheroo_client_ops *ops
客户端回调
struct pci_dev *vga_dev
绑定到当前音频客户端的pci设备
描述
注册音频客户端(GPU上的音频设备)。假定客户端使用运行时PM。在此之前,应调用vga_switcheroo_client_probe_defer()
以确保满足所有前提条件。
返回值
成功时返回0,内存分配错误时返回-ENOMEM,获取客户端id错误时返回-EINVAL。
-
bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)¶
是否推迟探测给定客户端
参数
struct pci_dev *pdev
客户端pci设备
描述
确定是否未满足任何前提条件来探测给定客户端。驱动程序应在其->probe回调中尽早调用此方法,如果评估结果为true
,则返回-EPROBE_DEFER
。在你调用此函数之前,你不应该注册客户端。
返回值
如果应推迟探测,则返回true
,否则返回false
。
-
enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *pdev)¶
获取给定客户端的电源状态
参数
struct pci_dev *pdev
客户端pci设备
描述
从vga_switcheroo获取给定客户端的电源状态。该函数仅从hda_intel.c调用。
返回值
电源状态。
-
void vga_switcheroo_unregister_client(struct pci_dev *pdev)¶
注销客户端
参数
struct pci_dev *pdev
客户端pci设备
描述
注销客户端。如果这是一个vga客户端(GPU),则禁用vga_switcheroo。
-
void vga_switcheroo_client_fb_set(struct pci_dev *pdev, struct fb_info *info)¶
设置给定客户端的帧缓冲区
参数
struct pci_dev *pdev
客户端pci设备
struct fb_info *info
帧缓冲区
描述
设置给定客户端的帧缓冲区。切换时,控制台将重新映射到此缓冲区。
-
int vga_switcheroo_lock_ddc(struct pci_dev *pdev)¶
暂时将DDC线路切换到给定客户端
参数
struct pci_dev *pdev
客户端pci设备
描述
暂时将DDC线路切换到由pdev标识的客户端(但保持输出切换到它们所在的位置)。这允许非活动客户端探测EDID。之后必须通过调用vga_switcheroo_unlock_ddc()
将DDC线路切换回去,即使此函数返回错误也是如此。
返回值
成功时的先前DDC所有者,如果出错,则返回负整数。具体来说,如果没有注册处理程序或者处理程序不支持切换DDC线路,则返回-ENODEV
。此外,处理程序返回的负值会传播回调用方。返回值仅对可能对其感兴趣的任何调用方具有信息目的。可以忽略返回值,而仅依赖于后续EDID探测的结果,如果DDC切换失败,则结果将为NULL
。
-
int vga_switcheroo_unlock_ddc(struct pci_dev *pdev)¶
将DDC线路切换回先前的所有者
参数
struct pci_dev *pdev
客户端pci设备
描述
在调用vga_switcheroo_lock_ddc()
之后,将DDC线路切换回先前的所有者。即使vga_switcheroo_lock_ddc()
返回错误,也必须调用此函数。
返回值
成功时的先前DDC所有者(即pdev的客户端标识符),如果出错,则返回负整数。具体来说,如果没有注册处理程序或者处理程序不支持切换DDC线路,则返回-ENODEV
。此外,处理程序返回的负值会传播回调用方。最后,不允许在没有首先调用vga_switcheroo_lock_ddc()
的情况下调用此函数,并将导致-EINVAL
。
-
int vga_switcheroo_process_delayed_switch(void)¶
延迟切换的助手函数
参数
void
无参数
描述
如果存在挂起的延迟切换,则进行处理。
返回值
成功时返回0。如果没有挂起的延迟切换,如果客户端在此期间已注销,或者如果存在阻止切换的其他客户端,则返回-EINVAL。如果实际切换失败,则报告错误并返回0。
-
int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain)¶
驱动程序电源控制的助手函数
参数
struct device *dev
vga客户端设备
struct dev_pm_domain *domain
电源域
描述
用于其电源状态由驱动程序的运行时pm控制的GPU的助手函数。在GPU挂起后,需要调用处理程序以切断GPU的电源。同样,在GPU可以恢复之前,需要恢复电源。为此,此助手函数通过对处理程序的必要调用来扩充挂起/恢复功能。它只需要在电源开关与被断电的设备分开的平台上调用。
公共结构¶
-
struct vga_switcheroo_handler¶
处理程序回调
定义:
struct vga_switcheroo_handler {
int (*init)(void);
int (*switchto)(enum vga_switcheroo_client_id id);
int (*switch_ddc)(enum vga_switcheroo_client_id id);
int (*power_state)(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state);
enum vga_switcheroo_client_id (*get_client_id)(struct pci_dev *pdev);
};
成员
init
初始化处理程序。可选。当启用vga_switcheroo时,即当两个vga客户端已注册时,将调用此方法。它允许处理程序执行一些依赖于vga客户端存在的延迟初始化。目前只有radeon和amdgpu驱动程序使用此方法。返回值将被忽略
switchto
将输出切换到给定客户端。强制。对于非复用机器,这应该是一个空操作。返回0表示成功,否则表示失败(在这种情况下,切换将被中止)
switch_ddc
将DDC线路切换到给定客户端。可选。成功时应返回先前的DDC所有者,失败时返回负整数
power_state
切断或恢复给定客户端的电源。可选。返回值将被忽略
get_client_id
确定给定pci设备是集成GPU还是独立GPU。强制
描述
处理程序回调。复用器本身。switchto和get_client_id方法是强制的,所有其他方法都可以设置为NULL。
-
struct vga_switcheroo_client_ops¶
客户端回调
定义:
struct vga_switcheroo_client_ops {
void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
void (*reprobe)(struct pci_dev *dev);
bool (*can_switch)(struct pci_dev *dev);
void (*gpu_bound)(struct pci_dev *dev, enum vga_switcheroo_client_id);
};
成员
set_gpu_state
为卡执行相当于挂起/恢复的操作。强制。这不应切断独立GPU的电源,这是处理程序的工作
reprobe
轮询输出。可选。这会在唤醒GPU并将输出切换到GPU后调用
can_switch
检查设备现在是否处于可以切换的位置。强制。如果用户空间进程已打开其设备文件之一,则客户端应返回false
gpu_bound
在GPU绑定时通知音频客户端客户端ID。
描述
客户端回调。客户端可以是GPU或GPU上的音频设备。set_gpu_state和can_switch方法是强制的,reprobe可以设置为NULL。对于音频客户端,reprobe成员是虚假的。OTOH,gpu_bound仅适用于音频客户端,而不适用于GPU客户端。
公共常量¶
-
enum vga_switcheroo_handler_flags_t¶
处理程序标志位掩码
常量
VGA_SWITCHEROO_CAN_SWITCH_DDC
处理程序是否能够单独切换DDC线路。这向客户端发出信号,表明它们应该调用
drm_get_edid_switcheroo()
来探测EDIDVGA_SWITCHEROO_NEEDS_EDP_CONFIG
处理程序是否无法单独切换AUX通道。这向客户端发出信号,表明活动GPU需要训练链路并将链路参数传达给非活动GPU(通过vga_switcheroo调解)。然后,非活动GPU可以跳过AUX握手并使用这些预校准的值设置其输出(DisplayPort规范v1.1a,第2.5.3.3节)
描述
处理程序标志位掩码。处理程序在向vga_switcheroo注册时使用它来声明其功能。
-
enum vga_switcheroo_client_id¶
客户端标识符
常量
VGA_SWITCHEROO_UNKNOWN_ID
分配给vga客户端的初始标识符。确定id需要处理程序,因此GPU在vga_switcheroo_enable()中以延迟方式获得其真实id
VGA_SWITCHEROO_IGD
集成显卡设备
VGA_SWITCHEROO_DIS
独立显卡设备
VGA_SWITCHEROO_MAX_CLIENTS
目前最多支持两个GPU
描述
客户端标识符。音频客户端使用相同的标识符&0x100。
-
enum vga_switcheroo_state¶
客户端电源状态
常量
VGA_SWITCHEROO_OFF
关
VGA_SWITCHEROO_ON
开
VGA_SWITCHEROO_NOT_FOUND
客户端未向vga_switcheroo注册。仅在
vga_switcheroo_get_client_state()
中使用,而vga_switcheroo_get_client_state()
又仅从hda_intel.c调用
描述
客户端电源状态。
私有结构¶
-
struct vgasr_priv¶
vga_switcheroo私有数据
定义:
struct vgasr_priv {
bool active;
bool delayed_switch_active;
enum vga_switcheroo_client_id delayed_client_id;
struct dentry *debugfs_root;
int registered_clients;
struct list_head clients;
const struct vga_switcheroo_handler *handler;
enum vga_switcheroo_handler_flags_t handler_flags;
struct mutex mux_hw_lock;
int old_ddc_owner;
};
成员
active
是否启用vga_switcheroo。前提是注册两个GPU和一个处理程序
delayed_switch_active
是否存在挂起的延迟切换
delayed_client_id
挂起延迟切换的客户端
debugfs_root
vga_switcheroo debugfs接口的目录
registered_clients
已注册GPU的数量(仅计算vga客户端,不计算音频客户端)
clients
已注册客户端的列表
handler
已注册处理程序
handler_flags
已注册处理程序的标志
mux_hw_lock
保护复用器状态(尤其是在临时切换DDC线路时)
old_ddc_owner
将在解锁时切换回DDC线路的客户端
描述
vga_switcheroo私有数据。目前每个系统仅支持一个vga_switcheroo实例。
-
struct vga_switcheroo_client¶
已注册客户端
定义:
struct vga_switcheroo_client {
struct pci_dev *pdev;
struct fb_info *fb_info;
enum vga_switcheroo_state pwr_state;
const struct vga_switcheroo_client_ops *ops;
enum vga_switcheroo_client_id id;
bool active;
bool driver_power_control;
struct list_head list;
struct pci_dev *vga_dev;
};
成员
pdev
客户端pci设备
fb_info
在切换时控制台重新映射到的帧缓冲区
pwr_state
如果使用手动电源控制,则为当前电源状态。对于驱动程序电源控制,请调用vga_switcheroo_pwr_state()。
ops
客户端回调
id
客户端标识符。确定id需要处理程序,因此gpu最初分配了VGA_SWITCHEROO_UNKNOWN_ID,然后在vga_switcheroo_enable()中给出了它们的真实id
active
当前输出是否切换到此客户端
driver_power_control
电源状态是否由驱动程序的运行时pm控制。如果为true,则将ON和OFF写入vga_switcheroo debugfs接口是一个空操作,因此不会干扰运行时pm
list
客户端列表
vga_dev
pci设备,指示哪个GPU绑定到当前音频客户端
描述
已注册客户端。客户端可以是GPU或GPU上的音频设备。对于音频客户端,fb_info和active成员是虚假的。对于GPU客户端,vga_dev是虚假的。
处理程序¶
apple-gmux处理程序¶
gmux是内置于MacBook Pro中的微控制器,用于支持双GPU:pre-retinas上的Lattice XP2,pre-T2 retinas上的Renesas R4F2113。
在T2 Macbooks上,gmux是T2协处理器的SMC的一部分。SMC具有与NXP PCAL6524 GPIO扩展器的I2C连接,该扩展器启用/禁用独立GPU的稳压器,驱动显示面板电源,并具有一个GPIO来切换eDP复用器。Intel CPU可以通过MMIO与gmux交互,类似于控制主SMC接口的方式。
(MacPro6,1 2013也有一个gmux,但是尚不清楚原因,因为它具有双GPU,但没有内置显示器。)
gmux连接到南桥的LPC总线。根据微控制器的不同,其I/O端口的访问方式也不同:访问pre-retina gmux的驱动程序函数以_pio_
作为后缀,pre-T2 retina gmux的驱动程序函数以_index_
作为后缀,T2 Macs上的驱动程序函数以_mmio_
作为后缀。
gmux还连接到南桥的GPIO引脚,因此能够触发ACPI GPE。ACPI名称GMGP保存此GPIO引脚的编号。在MBP5 2008/09上,它是Nvidia MCP79的GPIO引脚22,在以下几代产品中,它是Intel PCH的GPIO引脚6,在MMIO gmux上,它是引脚21。
GPE仅表示发生了中断,实际事件类型是通过读取gmux寄存器来识别的。
除了GMGP名称外,gmux的ACPI设备还有两种方法GMSP和GMLV。GMLV可能表示“GMUX级别”,并读取GPIO的值,而GMSP可能表示“GMUX设置极性”,并且似乎写入GPIO的值。在较新的Macbooks上(这是在MacBookPro14,3之前或之后的某个时间引入的),ACPI GPE方法区分OS类型:在Darwin上,仅发出通知信号,而在其他OS上,读取GPIO的值然后反转。
由于Linux伪装成Darwin,因此最终进入仅通知代码路径。在MMIO gmux上,这似乎导致我们无法清除中断,除非我们调用GMSP(0)。没有这个,会涌现无法清除的状态=0中断。此问题似乎是MMIO gmux独有的。
图形复用器¶
在 pre-retina 型号上,两个 GPU 的 LVDS 输出都连接到 gmux,gmux 会将其中一个输出复用到面板。gmux 的一个技巧是在切换时延长其输出的消隐间隔,以使其与切换到的 GPU 同步。这允许用户察觉不到的无闪烁切换(US 8,687,007 B2)。
在 retina 型号上,复用不再由 gmux 本身完成,而是由一个单独的芯片完成,该芯片由 gmux 控制。该芯片有三个来源,分别是 NXP CBTL06142、TI HD3SS212 或 Pericom PI3VDP12412。面板使用 eDP 而不是 LVDS 驱动,因为 retina 分辨率所需的像素时钟超过了 LVDS 的限制。
Pre-retina 型号能够单独切换面板的 DDC 引脚。这由 TI SN74LV4066A 处理,它由 gmux 控制。因此,非活动 GPU 可以在不切换整个面板的情况下探测面板的 EDID。Retina 型号缺少此功能,因为用于 eDP 复用的芯片无法单独切换 AUX 通道(请参阅链接的数据表,Pericom 能够做到,但未被使用)。但是,retina 面板在其 DPCD 中设置了 NO_AUX_HANDSHAKE_LINK_TRAINING 位,允许非活动 GPU 跳过 AUX 握手,并使用活动 GPU 预先校准的链路参数设置输出。
外部 DP 端口仅在最初的两代一体式 MacBook Pro 上完全可切换,即 MBP5 2008/09 和 MBP6 2010。这由 NXP CBTL06141 完成,它由 gmux 控制。它是 retina 型号上 eDP 复用器的前身,区别在于支持 2.7 与 5.4 Gbit/s。
以下几代 MacBook Pro 用组合的 DP/Thunderbolt 端口取代了外部 DP 端口,并失去了在 GPU 之间切换它的能力,将其连接到独立 GPU 或 Thunderbolt 控制器。奇怪的是,虽然完整的端口不再可切换,但 AUX 和 HPD 仍然可以通过 NXP CBTL03062(在 pre-retina 型号 MBP8 2011 和 MBP9 2012 上)或两个 TI TS3DS10224(在 pre-T2 retina 型号上)在 gmux 的控制下切换。由于集成 GPU 缺少主链路,因此外部显示器对其显示为幻像,无法进行链路训练。
gmux 接收所有显示连接器的 HPD 信号,并在热插拔时发送中断。在无法切换外部端口的几代产品中,可以唤醒独立 GPU 以驱动新连接的显示器。在这些代产品上切换 AUX 的能力可以用于提高热插拔检测的可靠性,方法是让集成 GPU 在独立 GPU 休眠时轮询端口,但目前我们没有利用此功能。
我们对外部端口的切换策略是,在能够完全切换它的几代产品中,当向 vga_switcheroo 发出 IGD / DIS 命令时,端口与面板一起切换。因此,可以使用集成 GPU 在电池供电情况下驱动例如投影仪。如果需要更高的性能,用户可以手动切换到独立 GPU。
在所有较新的代产品中,外部端口只能由独立 GPU 驱动。如果在面板切换到集成 GPU 时插入显示器,两个 GPU 都将被使用以获得最大性能。为了降低功耗,用户可以手动切换到独立 GPU,从而挂起集成 GPU。
gmux 在启动时的初始切换状态可通过 EFI 变量 gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9
(第 5 个字节,1 = IGD,0 = DIS)配置。根据此设置,EFI 固件告诉 gmux 切换面板和外部 DP 连接器,并为所选 GPU 分配帧缓冲区。
电源控制¶
gmux 能够切断独立 GPU 的电源。它会自动处理正确的序列,以拆卸和启动核心电压、VRAM 和 PCIe 的电源轨。
背光控制¶
在单 GPU MacBook 上,背光的 PWM 信号由 GPU 生成。相比之下,在双 GPU MacBook Pro 上,可以挂起任一 GPU 以节省能量。因此,PWM 信号需要由单独的背光驱动程序生成,该驱动程序由 gmux 控制。最早的 MBP5 2008/09 代使用 TI LP8543 背光驱动程序。较新的型号使用 TI LP8545 或 TI LP8548。
公共函数¶
参数
struct pnp_dev *pnp_dev
要探测的设备,如果为 NULL,则使用第一个匹配的设备
enum apple_gmux_type *type_ret
(通过引用)返回设备的 apple_gmux_type
描述
通过实际探测来检测是否存在受支持的 gmux 设备。这避免了 apple_gmux_present()
在某些型号上返回的误报。
返回值
如果检测到受支持的 gmux ACPI 设备,并且内核已配置 CONFIG_APPLE_GMUX,则为 true
,否则为 false
。
-
bool apple_gmux_present(void)¶
检查是否存在 gmux ACPI 设备
参数
void
无参数
描述
驱动程序可以使用此功能来激活特定于双 GPU MacBook Pro 和 Mac Pro 的怪癖,例如延迟探测、运行时电源管理和背光。
返回值
如果存在 gmux ACPI 设备并且内核已配置 CONFIG_APPLE_GMUX,则为 true
,否则为 false
。