本文主要是從如下幾個方面介紹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="{"mod":"popu_376","con":",https://blog.csdn.net/arag2009/article/details/78465854,"}" data-track-click="{"mod":"popu_376","con":",https://blog.csdn.net/arag2009/article/details/78465854,"}">閱讀更多</a>
</div>
</article>