xserver相關知識彙總

xserver相關知識彙總
轉載QTVLC 最後發佈於2018-08-16 13:41:52 閱讀數 726 收藏
展開
本文主要是從以下幾個方面介紹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: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: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驅動初始化相關的內容做了一次簡單的瀏覽。



閱讀更多


1
2
3
4
5
6

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章