[转帖]xserver相关知识汇总

xserver相关知识汇总

https://blog.csdn.net/QTVLC/article/details/81739984

本文主要是从以下几个方面介绍xorg-xserver 相关的知识

1.linux系统图形界面框架

2.xserver 和x client启动过程

3.图形2d,3d加速原理简介

4.xserver主分支代码解析。

5.xserver,xclient协议简介

6.一个基于Xlib的简单例子解析

7.radeon驱动初始化代码解析.

1.linux图形界面框架

参考至:http://dzdl.ipchina.org/site/?uid-9-action-viewspace-itemid-49

linux图形界面又称x系统,其主要包含如下几个部分:

a)xserver

b)显示管理器 (Display Manager) 例如(gdm  kdm xdm等)

c)窗口管理器 (Window Manager) 例如(metacity ,fluxbox等)

d)DM 和 WM之上的一些图形应用程序

在使用中一般都是b,c,d三者集合起来构成一个完整的集成工作环境,例如KDE ,GNOME等

,这就是我们平时所说的广义上的xclient

a)xserver 主要提供基本的显示接口共xclient使用,并将用户的操作等也反映给xclient,

是xclient与硬件的一个中间层。xserver相关的两个主要部分是

(1)    xorg.conf

xorg.conf是X Server的主要配置文件,它包含一个当前系统的硬件资源列表。X Server就是根据这些硬件资源“组织”出基本的图形能力。xorg.conf文件在/etc/X11/xorg.conf,主要包含几个字段:

Files:            X系统使用的字体存放目录(字体的具体使用由FontConfig工具主持)

InputDevice:    输入设备,如键盘鼠标的信息

Monitor:        显示器的设置,如分辨率,刷新率等

Device:            显示卡信息

Screen:            由Monitor和Device组装成一个Screen,表示由它们向这个Screen提供输出能力

ServerLayout:    将一个Screen和InputDevice组装成一个ServerLayout

在具有多个显示设备的系统中,可能有多个Screen和多个ServerLayout,用以实现不同的硬件搭配。

在最近的xorg版本中,X Server已经开始自动侦测硬件,现在的xorg.conf已经都成了默认名称。具体细节还待查,但基本原理还是不变的。

(2) X session(X会话)

X session是指X server启动后直到X server关闭之间的这段时间。这期间一切跟X相关的动作都属于X session的内容。管理X session的程序称为Display Manager,常听说的gdm或kdm就是gnome/kde所分别对应的Display Manager。

开启一个X session,也就是开始了图形界面的使用。在开启的过程中,Display Manager会对用户进行认证(也就是用户名密码的输入),运行事先设置好的程序(比如scim输入法就是这个时候启动的)等等。

这个开启过程要执行的一系列操作都可以在/etc/X11/Xseesion以及/etc/X11/Xsession.d/目录下看到,其他还有一些配置文件如Xsession.options, Xresource等,都是执行的X session的初始化过程。仔细阅读这些脚本或配置文件,可以帮助你更好地理解X

b), Display Manager

上面说过,Display Manager(后简称DM)是管理X session的程序,常见的有gdm, kdm, xdm等。对于默认进入X界面的Linux系统,必须将DM程序在开机时执行,即:/etc/rc2.d/S13gdm。下面我们从手工启动X的过程,看一下DM为我们做了哪些工作。

如果没有设置DM在开机时运行的话,手动启动X使用startx命令。

man startx

可以知道,startx的作用可以看作是Display Manager的一种隐性实现。它使用xinit命令,分别根据/etc/X11/xinit/xinitrc和/etc/X11/xinit/xserverrc中所指定的设置唤起X。

其中,xserverrc执行X server的运行任务;xinitrc则运行Xsession命令。从/etc/X11/Xsession脚本的内容可以看出,它也就是进入/etc /X11/Xsession.d/目录轮询地执行所有脚本。很明显,这些也就是前面所说的Xsession初始化工作。

综合起来说,Display Manager完成三个任务:1, X Server的启动; 2, X session的初始化; 3, X session的管理。

c), Window Manager

X Server提供了基本的图形显示能力。然而具体怎么绘制应用程序的界面,却是要有应用程序自己解决的。而Window Manager(桌面管理器,后简称WM)就是用来提供统一的GUI组件的(窗口、外框、菜单、按钮等)。否则,应用程序们各自为政,既增加了程序开发的负担,不统一的桌面风格对视觉也是不小的挑战。

WM的启动由DM控制,在gdm的登录窗口,我们可以进行选择。常见的WM有:Metacity(Gnome默认的WM), fluxbox, fvwm, E17等。

d), X Clients

最后,就是X Client了。X客户端程序,顾名思义,就是使用X服务的程序。firefox,gedit等等都属于X Client程序。X Client部分值得考虑一下的就是DISPLAY环境变量。它主要用于远程X Client的使用。该变量表示输出目的地的位置,由三个要素组成:

[host]:display[.screen]

host指网络上远程主机的名称,可以是主机名、IP地址等。默认的host是本地系统,你可以在自己系统上echo $DISPLAY看一下。

display和screen分别代表输出画面的编号和屏幕的编号。具体细节由于硬件的缺乏,还有待进一步研究。

2.xserver 和x client启动过程

参考:http://blog.csdn.net/clozxy/archive/2010/04/15/5488699.aspx

对xserver和x client的启动过程的探讨主要是对startx命令的探讨

startx脚本网上解释的很多,这里就不多做介绍,对startx介绍分以下两个部分

(1)xinit用法

startx其实是个脚本,最终调用的是xinit命令,其用法如下:

xinit 的用法为: xinit [[client] options ] [– [server] [display] options] 。其中 client 用于指定一个基于 X 的应用程序, client 后面的 options 是传给这个应用程序的参数, server 是用于指定启动哪个 X 服务器,一般为 /usr/bin/X 或 /usr/bin/Xorg , display 用于指定 display number ,一般 为 0 ,表示第一个 display , option 为传给 server 的参数。

如果不指定 client , xinit 会查找 HOME ( 环境变量 ) 目录下的 .xinitrc 文件,如果存在这个 文件, xinit 直接调用 execvp 函数执行该文件。如果这个文件不存在,那么 client 及其 options 为:  xterm -geometry +1+1 -n login -display :0 。

如果不指定 server , xinit 会查找 HOME( 环境变量 ) 目录下的 .xserverrc 文件,如果存在这个文件, xinit 直接调用 execvp 函数执行该文件。如果这个文件 不存在,那么 server 及其 display 为:  X :0 。如果系统目录中不存在 X 命令,那么我们需要在系统目录下建立一个名为 X 的链接,使其指向真正的 X server 命令( Ubuntu 下为 Xorg )。

因此startx的用法跟xinit一样:startx [ [ client ] options … ] [ – [ server ] options … ]

(2)startx的几种启动方式

由对 startx 脚本的分析,我们可以知道 startx 主要有三种启动方式:

a) 、一种是自己指定要启动的 client 和 server , 例如: startx /usr/bin/xclock – /usr/bin/X :0 ;

b)、一种是通过在 $HOME 下新建 .xinitrc 文件来指定要启动的多个 client 和 .xserverrc 来指定要启动的 server;

c)、还有一种是直接输入 startx 而不指定参数,这也就是我们启动 gnome 桌面的方法。

在 c 这种启动方法中, startx 脚本会先去看系统目录( /etc/X11/xinit/ )下的 rc 文件是否存在,如果不存在就会用默认的 xterm 和 /usr/bin/X 来启动 xinit 。显然, startx 启动的不是 xterm ,而是 gnome 桌面,因此 gnome 的启动是通过系统文件 /etc/X11/xinit/xinitrc 来指定的。

而 /etc/X11/xinit/xinitrc 文件的内容如下所示:

#!/bin/bash  # 注意 : 该脚本用的是 bash shell 解析的

# Xorg:xinitrc.cpp,v1.32000/08/1719:54:30cpqbldExpXorg:xinitrc.cpp,v1.32000/08/1719:54:30cpqbldExp

# /etc/X11/xinit/xinitrc

#

# global xinitrc file, used by all X sessions started by xinit (startx)

# invoke global X session script

. /etc/X11/Xsession   # 在当前这个 shell 环境中执行 Xsession 脚本

因此, gnome 的启动应该在 Xsession 里。

而 X Server 的启动则是通过系统文件 /etc/X11/xinit/xserverrc 来指定的 , 这个文件的内容为 :

#!/bin/sh # 注意:该脚本用的是 Bourne shell 解析的

# Id:xserverrc1892005−06−1100:04:27ZbrandenId:xserverrc1892005−06−1100:04:27Zbranden

exec /usr/bin/X11/X -nolisten tcp

综上所述, startx 的默认启动过程为: startx 调用并将系统文件 /etc/X11/xinit/xinitrc 和 /etc/X11/xinit/xserverrc 作为参数传给 xinit , xinit 就会先执行系统文件 /etc/X11/xinit/xserverrc 以启动 X Server ,然后执行 /etc/X11/xinit/xinitrc ,而 xinitrc 则会执行脚本 /etc/X11/Xsession ,而 Xsession 则会按顺序调用执行 /etc/X11/Xsession.d 目录下的文件,从而最终调用了 gnome-session 这个用于 启动 GNOME 桌面环境的程序

3.图形2d,3d加速简介

为了是linux下图形更加流畅,必须使用加速。常用的加速方法如下

加速常见有三种方式

a)ShadowFB

ShadowFB是xserver自带的与体系结构无关的2D加速方式,它将系统framebuffer复制一份,并且在拷贝回framebuffer中实现图形旋转等操作,这样可以起到一定加速作用,但是效果不好。

b) XAA

XAA全称XFree86 Acceleration Architecture,是由 Harm Hanemaayer 在1996年写的一个显卡硬件2D加速的驱动结构,目前大多数的显卡去动均支持这种驱动模式

c) EXA

EXA是X.Org发起的用于取代XAA加速的驱动结构,修改的宗旨是是XRender更加好用。

历史上对2D 和3D加速已经做了区分,2D加速主要使用的是XAA结构,3D加速主要是通过DRM(Direct Rendering Manage) 提供.而EXA提供了比XAA更好集成XRender的结构,同时也提高了XAA的2D加速效果。

EXA采用的方法是通过实现对OpenGL的加速以实现同时对2D,3D图像的加速,这样2D图像就可以看作是3D图像的一个子集。

4.xserver 主分支代码解析

参考网站:http://xwindow.angelfire.com,

基于xorg-xserver-1.7.6版本

xserver代码是从dix/main.c中的main函数开始执行。

开始的一系列函数执行一些初始化及check的工作

InitRegions();

pixman_disable_out_of_bounds_workaround();

CheckUserParameters(argc, argv, envp);

CheckUserAuthorization();

InitConnectionLimits();

ProcessCommandLine(argc, argv);

随后main函数进入了一个死循环。每次循环均包含了

a)xserver初始化

b)xserver循环处理client消息

c)xserver退出

三个阶段

这是xserver的main函数最外层的循环,一般启动xserver只会执行一次循环:用户在图形界面操作时,实际上xserver是处在b)阶段。

这个循环就保证了xserver出现一般的异常时会自动恢复,比如在运行x时替换了其显卡驱动,xserver会触发异常结束第一次循环

并在第二次循环中重新加载替换后的显卡驱动。

以下分别对这三个阶段做解析

a)xserver初始化

xserver初始化函数非常多,以下仅粗略介绍几个比较熟悉的:

(1)

初始化中有如下代码:

if(serverGeneration == 1)

{

CreateWellKnownSockets();

InitProcVectors();

for (i=1; i<MAXCLIENTS; i++)

clients[i] = NullClient;

serverClient = xalloc(sizeof(ClientRec));

if (!serverClient)

FatalError(“couldn’t create server client”);

InitClient(serverClient, 0, (pointer)NULL);

}

else

ResetWellKnownSockets ();

当第一次循环时serverGeneration=1,执行的是第一个分支代码。

CreateWellKnownSockets() 初始化一系列sockets监听是否有clients申请连接。

InitProcVectors() 初始化ProcVector,SwappedProcVector结构

for循环是生成并初始化clients数组

之后便是serverClient变量的生成即初始化,serverClient是clients数组中索引为0的项,因为他是拥有root window的client。

当之后的循环时serverGeneration = 0,执行的是ResetWellKnownSockets即重置sockets工作。

(2)

InitOutput()是初始化分量较中的一环,处理过程可以分为如下部分:

1)xf86HandleConfigFile 解析xorg.con文件 ,获得xserver的配置信息。

2)xf86BusProbe  获得video的pci信息,例如framebuffer地址等。

3)DoConfigure() 根据配置文件 ,或者传进来的参数做相应的配置

4)xf86LoadModules load  xorg.conf中配置的一系列模块

5)以此遍历注册的各个driver,调用其identify,probe函数, 这样就根据显卡的型号加载了相应的驱动

6)匹配screen,主要是根据xorg.conf中配置的screen,查询是否有与其匹配的device

7)遍历screen,调用其匹配device驱动的PreInit函数。这样就完成了显卡驱动的预初始化

8)遍历screen,调用AddScreen函数,分配screenInfo.screen[]的一项,并做初始化ScreenInit.这样驱动的初始化基本完成。

(3)

InitInput()是初始化输入设备,例如键盘和鼠标等。如果xorg.conf中有Section InputDevice配置,会按照

其配置扫描加载设备

b)xserver循环处理client消息

在初始化结束之后xserver便进入了循环处理阶段即

Dispatch()函数

该函数的流程主要是一个循环结构

while (!dispatchException)

即当不出现异常时循环会不断进行下去

每一次循环可以分为如下部分

(1)接受用户的输入,并发送给client

if (*icheck[0] != *icheck[1])

{

ProcessInputEvents();

FlushIfCriticalOutputPending();

}

(2)等待clients发送事件过来

nready = WaitForSomething(clientReady);

(3)遍历每个发送信息的client,做如下处理

1)接受用户输入并发送

if (*icheck[0] != *icheck[1])

ProcessInputEvents();

FlushIfCriticalOutputPending();

2)获得client的请求号

result = ReadRequestFromClient(client);

3) 根据请求号调用队列中相应的处理函数

if (result > (maxBigRequestSize << 2))

result = BadLength;

else {

result = XaceHookDispatch(client, MAJOROP);

if (result == Success)

result = (* client->requestVector[MAJOROP])(client);

XaceHookAuditEnd(client, result);

}

4)若处理函数返回异常则做异常处理

if (result != Success)

{

if (client->noClientException != Success)

CloseDownClient(client);

else

SendErrorToClient(client, MAJOROP,

MinorOpcodeOfRequest(client),

client->errorValue, result);

break;

}

}

5)提交处理结果

FlushAllOutput();

由此Dispatch函数解析结束

c)xserver退出

包含了一系列释放内存,关闭clients等操作,这里就不多做解析。

5.xserver,xclient协议简介

由上文对Dispatch函数的分析可以看出,xserver对client的处理主要是三步:

(1)获得事件信息

nready = WaitForSomething(clientReady);

(2)获得操作号

result = ReadRequestFromClient(client);

(3)根据操作号处理

result = (* client->requestVector[MAJOROP])(client);

因此其操作号和操作的对应是xserver与client的协议的一部分,类似操作

系统的系统调用号和系统调用之间的关系。

在上面介绍InitClients()中有对requestVector初始化

client->requestVector = InitialVector;

InitVector如下:

int (* InitialVector[3]) (

ClientPtr

) =

{

0,

ProcInitialConnection,

ProcEstablishConnection

};

其只有两个函数,一个是初始化Connection,一个是确立Connection

在ProcEstablishConnection中调用SendConnSetup寒酸,

SendConnSetup函数有:

client->requestVector = client->swapped ? SwappedProcVector : ProcVector;

即初始化requestVector为SwappedProcVector或ProcVector

ProcVector如下:

_X_EXPORT int (* ProcVector[256]) (

ClientPtr

) =

{

ProcBadRequest,

ProcCreateWindow,

ProcChangeWindowAttributes,

ProcGetWindowAttributes,

ProcDestroyWindow,

ProcDestroySubwindows,

ProcChangeSaveSet,

ProcReparentWindow,

ProcMapWindow,

ProcMapSubwindows,

ProcUnmapWindow,

。。。。。。。。。。。。。

ProcGetModifierMapping,

0,

0,

0,

0,

0,

0,

0,

ProcNoOperation

};

SwappedProcVector类似。

也就是说Client与server交互时,先按照固定的协议初始化Connector,并且告诉xserver其适合的协议。

然后server按照该协议解析client发送过来的操作号。

6.一个基于Xlib的简单例子了解Client流程

Xlib是对X协议的的一个简单的封装,可以让程序员不用了解细节而编写图形相关程序。实际上程序员直接调用Xlib的很少,更多使用的是

GTK+ ,QT等图形库。这些又是基于Xlib的图形库。

一个简单的Xlib例子如下

#include <X11/Xlib.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main(void) {

Display *d;

Window w;

XEvent e;

char *msg = “Hello, World!”;

int s;

d = XOpenDisplay(NULL);

if (d == NULL) {

fprintf(stderr, “Cannot open display\n”);

exit(1);

}

s = DefaultScreen(d);

w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,

BlackPixel(d, s), WhitePixel(d, s));

XSelectInput(d, w, ExposureMask | KeyPressMask);

XMapWindow(d, w);

while (1) {

XNextEvent(d, &e);

if (e.type == Expose) {

XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);

XDrawString(d, w, DefaultGC(d, s), 50, 50, msg, strlen(msg));

}

if (e.type == KeyPress)

break;

}

XCloseDisplay(d);

return 0;

}

这个程序就可以看作一个简单的client,包含client的大体流程。

编译: gcc input.c -o output -lX11

程序执行方式有两种:

1.在图形界面下直接执行程序

2.在用户目录下新建一个.xinitrc文件,写入

exec input

之后startx,执行的不是默认的图形界面程序而是input程序

7.radeon驱动初始化代码解析.

由上面对xserver初始化的介绍,可以看到,在初始化过程中主要是显卡驱动的三个函数的调用

Probe , PreInit , ScreenInit

以下以radeon驱动为例(xorg-xserver-video-ati-6.13.1),介绍驱动对显卡的初始化过程,以及图形加速中使用的函数。

(1)Probe函数

在radeon驱动中,probe函数主要是

static Bool

radeon_pci_probe(

DriverPtr          pDriver,

int                entity_num,

struct pci_device *device,

intptr_t           match_data

)

{

return radeon_get_scrninfo(entity_num, (void *)device);

}

在radeon_get_scrninfo函数中有:主要是对pScrn和pENT的初始化。

在pScrn的初始化中给出了将要调用的PreInit 和ScreenInit函数

#ifdef XF86DRM_MODE

if (kms == 1) {

pScrn->PreInit       = RADEONPreInit_KMS;

pScrn->ScreenInit    = RADEONScreenInit_KMS;

pScrn->SwitchMode    = RADEONSwitchMode_KMS;

pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;

pScrn->EnterVT       = RADEONEnterVT_KMS;

pScrn->LeaveVT       = RADEONLeaveVT_KMS;

pScrn->FreeScreen    = RADEONFreeScreen_KMS;

pScrn->ValidMode     = RADEONValidMode;

} else

#endif

{

pScrn->PreInit       = RADEONPreInit;

pScrn->ScreenInit    = RADEONScreenInit;

pScrn->SwitchMode    = RADEONSwitchMode;

pScrn->AdjustFrame   = RADEONAdjustFrame;

pScrn->EnterVT       = RADEONEnterVT;

pScrn->LeaveVT       = RADEONLeaveVT;

pScrn->FreeScreen    = RADEONFreeScreen;

pScrn->ValidMode     = RADEONValidMode;

}

不妨已RADEONPreInit_KMS , RADEONScreenInit_KMS为例介绍驱动PreInit和ScreenInit过程

(2)PreInit

RADEONPreInit_KMS在结构上大体可以分为三个部分(虽然不严格),

a)pScrn->driverPrivate的初始化

例如:

info               = RADEONPTR(pScrn);

info->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);

f (!radeon_alloc_dri(pScrn))

return FALSE;

其实对pScrn->driverPrivate的初始化贯穿了整个PreInit,但是在前面比较集中。

b)drm的初始化

radeon_open_drm_master(pScrn)

调用drmOpen打开内核drm设备

drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8)

drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))

等做其他方面的初始化

c)一些相关模块的load

例如:

xf86LoadSubModule(pScrn, “fb”)

load framebuffer相关的so

!xf86LoadSubModule(pScrn, “ramdac”)

load 与光标显示相关模块

RADEONPreInitAccel_KMS(pScrn)

根据加速方式选择决定load shadowfb 还是exa模块

细节很多大体上可以分这三个部分理解

(3)ScreenInit

RADEONScreenInit_KMS要比RADEONPreInit_KMS杂乱

但也可以看作如下几个部分

a)对pScrn->driverPrivate的比较集中的初始化

例如:

info->bufmgr = radeon_bo_manager_gem_ctor(info->dri->drmFD);

info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);

等比较明显的

以及

radeon_setup_kernel_mem(pScreen);

初始化地址映射相关的info信息

b)fbScreenInit

初始化framebuffer信息

c) 显示图像像素相关的初始化及fbPictureInit

例如:

if (pScrn->bitsPerPixel > 8) {

VisualPtr  visual;

visual = pScreen->visuals + pScreen->numVisuals;

while (–visual >= pScreen->visuals) {

if ((visual->class | DynamicClass) == DirectColor) {

visual->offsetRed   = pScrn->offset.red;

visual->offsetGreen = pScrn->offset.green;

visual->offsetBlue  = pScrn->offset.blue;

visual->redMask     = pScrn->mask.red;

visual->greenMask   = pScrn->mask.green;

visual->blueMask    = pScrn->mask.blue;

}

}

}

fbPictureInit (pScreen, 0, 0);

#ifdef RENDER

if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {

if (strcmp(s, “RGB”) == 0) subPixelOrder = SubPixelHorizontalRGB;

else if (strcmp(s, “BGR”) == 0) subPixelOrder = SubPixelHorizontalBGR;

else if (strcmp(s, “NONE”) == 0) subPixelOrder = SubPixelNone;

PictureSetSubpixelOrder (pScreen, subPixelOrder);

}

#endif

这部分是fbPictureInit和对像素RGB顺序的初始化

d)BackStore相关的初始化

例如:

xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,

“Initializing backing store\n”);

miInitializeBackingStore(pScreen);

xf86SetBackingStore(pScreen);

e)加速函数相关的初始化

例如:

if (info->r600_shadow_fb) {

xf86DrvMsg(scrnIndex, X_INFO, “Acceleration disabled\n”);

info->accelOn = FALSE;

} else {

xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,

“Initializing Acceleration\n”);

if (RADEONAccelInit(pScreen)) {

xf86DrvMsg(scrnIndex, X_INFO, “Acceleration enabled\n”);

info->accelOn = TRUE;

} else {

xf86DrvMsg(scrnIndex, X_ERROR,

“Acceleration initialization failed\n”);

xf86DrvMsg(scrnIndex, X_INFO, “Acceleration disabled\n”);

info->accelOn = FALSE;

}

}

中的RADEONAccelInit(pScreen)函数

下面会对RADEONAccelInit(pScreen)函数做仔细的分析

f)光标显示相关的初始化

例如:

xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, “Initializing DPMS\n”);

xf86DPMSInit(pScreen, xf86DPMSSet, 0);

xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, “Initializing Cursor\n”);

xf86SetSilkenMouse(pScreen);

miDCInitialize(pScreen, xf86GetPointerScreenFuncs());

if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {

if (RADEONCursorInit_KMS(pScreen)) {

}

}

其中xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)的判断决定对光标显示是否使用硬件加速

g)其他的初始化

例如CloseScreen,BlockHandler 等变量赋值

Crtc初始化xf86CrtcScreenInit (pScreen)

和colormap相关的drmmode_setup_colormap(pScreen, pScrn)。

(4)RADEONAccelInit

需要重点介绍的是RADEONAccelInit函数,因为在这个函数中引入了初始化图像加速相关的函数

以笔者调试过的RS780为例:

其调用的图形加速相关的初始化是R600DrawInit(pScreen)函数,因为驱动不支持RS780的xaa加速,而软件加速shodowfb效果不好,必须使用exa加速。

R600DrawInit()函数中包含了众多加速函数的初始化其中最重要的是如下5系列函数

a)Solid相关的函数

info->accel_state->exa->PrepareSolid = R600PrepareSolid;

info->accel_state->exa->Solid = R600Solid;

info->accel_state->exa->DoneSolid = R600DoneSolid;

Solid即是向某一区域填充色的操作

b)Copy相关的函数

info->accel_state->exa->PrepareCopy = R600PrepareCopy;

info->accel_state->exa->Copy = R600Copy;

info->accel_state->exa->DoneCopy = R600DoneCopy;

Copy是不同区域直接拷贝的函数

c)Composite函数

info->accel_state->exa->CheckComposite = R600CheckComposite;

info->accel_state->exa->PrepareComposite = R600PrepareComposite;

info->accel_state->exa->Composite = R600Composite;

info->accel_state->exa->DoneComposite = R600DoneComposite;

Composite是不同窗口组合在一起的操作

d)UploadToScreen函数

info->accel_state->exa->UploadToScreen = R600UploadToScreenCS;

UploadToScreen是向framebuffer拷贝矩形域数据的函数

e)DownloadFromScreen函数

info->accel_state->exa->DownloadFromScreen = R600DownloadFromScreenCS;

DownloadFromScreen是从framebuffer拷贝出矩形域数据的函数

至此radeon驱动初始化相关的内容做了一次简单的浏览。

        </div>
            </div>
            <div class="hide-article-box text-center">
        <a class="btn btn-red-hollow" id="btn-readmore" data-track-view="{&quot;mod&quot;:&quot;popu_376&quot;,&quot;con&quot;:&quot;,https://blog.csdn.net/arag2009/article/details/78465854,&quot;}" data-track-click="{&quot;mod&quot;:&quot;popu_376&quot;,&quot;con&quot;:&quot;,https://blog.csdn.net/arag2009/article/details/78465854,&quot;}">阅读更多</a>
    </div>
        </article>

原文地址:https://www.cnblogs.com/jinanxiaolaohu/p/10647435.html

时间: 2024-10-21 23:26:08

[转帖]xserver相关知识汇总的相关文章

【干货】样品气体预处理系统相关知识汇总

武汉天禹智控科技有限公司依托多年来从事气体分析行业的经验和强大的技术实力,经过多年研制开发和应用实践,在传感技术方面,成功的研制出拥有自主知识产权的电化学分析仪系列,红外分析仪系列,紫外气体分析仪系列,激光分析仪系列,光声光谱气体分析仪系列,适用于各种工况的工业过程分析系统,同时可以根据客户需求进行气体分析仪个性定制,产品广泛应用于环保.冶金.石化.化工.能源.食品.农业.交通.水利.建筑.制药.酿造及科学研究等众多行业,并且得到用户的一直好评.现针对样品气体预处理系统相关知识汇总分享,供大家使

Logback相关知识汇总

例如:%-4relative 表示,将输出从程序启动到创建日志记录的时间 进行左对齐 且最小宽度为4格式修饰符,与转换符共同使用:可选的格式修饰符位于“%”和转换符之间.第一个可选修饰符是左对齐 标志,符号是减号“-”:接着是可选的最小宽度 修饰符,用十进制数表示.如果字符小于最小宽度,则左填充或右填充,默认是左填充(即右对齐),填充符为空格.如果字符大于最小宽度,字符永远不会被截断.最大宽度 修饰符,符号是点号"."后面加十进制数.如果字符大于最大宽度,则从前面截断.点符号“.”后面

开发过程中用到的相关知识汇总

干了四年的开发工作,学到不少,但是又忘记很多,想来需要归档,通过写文章提高个人的逻辑能力,寄此对以后有所帮助,同时温故而知新. 开发相关 语言相关 算法 数据库优化 linux系统 系能调优 工具 维护相关 监控工具 问题定位

[skill][https][ssl/tls] HTTPS相关知识汇总

结论前置: A 身份验证 证书, 服务器证书 B 密钥协商 RSA   DHE / ECDHE   PSK C 加密通信 加密通信采用对称加密,使用B阶段协商出来的密钥. B 阶段如果使用 RSA 协商,可以用服务器证书在协商过程中解密到 C过程中的密钥.从而解密通信内容.(此方式下,采用旁路方式就可以). B 阶段如果使用DHE/ECDHE协商,至少需要建立链接时的server魔数(也许还需要私钥即服务器证书)才能计算出加密密钥.简单来说协商过程也是一次一密. 于是,应该有两种情况可以解密ht

CEF3相关知识汇总(不断更新)

CEF全称是Chromium Embedded Framework,它是Chromium的Content API的封装库. CEF官网地址:https://bitbucket.org/chromiumembedded/cef CEF官方论坛:http://www.magpcss.org/ceforum CEFSharp:https://github.com/cefsharp/CefSharp ChromiumFX,.NET bindings for the Chromium Embedded F

java NIO中的Reactor相关知识汇总 (转)

一.引子 nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接.很多同学提起nio都能说起一二,但是细究其背后的原理.思想往往就开始背书,说来说去都是那么几句,其中不少人并不见的真的很理解.本人之前就属于此类,看了很多书和博客,但是大多数都只是讲了三件套和怎么使用,很少会很细致的讲背后的思想,那本次我们就来扒一扒吧.     很多博客描述nio都是这么说的:基于Reactor模式实现的多路非阻塞高性能的网络IO.那么我们就

【ShadowsSocks】相关知识汇总

1. 前戏篇 https://www.textarea.com/ExpectoPatronum/shiyong-shadowsocks-kexue-shangwang-265/ 2.高潮篇 https://zhensheng.im/2014/05/17/2230/MIAO_LE_GE_MI https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users https://github.com/ftao/vpn-deploy

javascript 字符串相关知识汇总

① charAt(): 选中字符串内第几个元素 <script> var str="1234567389"; alert( str.charAt(1) ); // 2 </script> ② charCodeAt():字符串内,选中的那个元素的编码 <script> var str="1234567389"; alert( str.charCodeAt(1) ); // 50 </script> ③ String.fr

InputStream和OutputStream及相关知识汇总

https://www.jianshu.com/p/e5bc7ea5f948 最近帮学姐写爬虫的时候遇到奇怪的问题,同样的程序在Mac上可以正常运行而在Windows上返回结果错误,最后经排查发现是Linux与Windows的默认编码方式不同,而自己的程序没有设置编码方式自动采用了默认的编码方式,所以导致错误发生.之后尝试了多种编码方式均告失败,最后发现是由于自己对输入输出流的认识不到位,没有正确使用的原因,故进行整理学习. 首先认识一下字节流与字符流.程序中的输入输出都是通过流的形式保存的,流