善用 XShm Extension 加速貼圖
如今的 Xorg 千變萬化,發展出各種(DRI/DRI2/EAA/EXA/UXA/AIGLX)等加速機制,更有極絢麗的 3D 視窗技術,一點也不讓 Mac OS 和 Windows 上的 3D 視窗特效專美於前。話雖如此,很多人們早已遺忘 X Window System 的歷史原由,我們反觀當年的 XFree86 就有如醜小鴨般,其為 Networking 考量的 Client/Server 架構,就是舊 Unix 終端機時代所留下的東西。到目前為止,隨著硬體速度越來越快,Client/Server 的界限雖被 DRI/DRI2/AIGLX 等技術逐漸打破,但無論如何,Xorg 大底上還是維持著 Client/Server 的本質。只不過應用程式層的軟體,因為經過各種 GTK/GDK/Qt 等 Graphical Toolkits 包裝後,多數開發者和使用者已經不會再看到 X 底層的運作模式。
這裡記載著一個簡單的範例程式,用來說明 X 如何利用 XImage 做貼圖運算,其主要是將 buffer(100x100x32bits 的影像)畫在視窗上,該 buffer 可以是讀取圖檔或是使用各種資料來源,為一塊記憶體。此程式將會用 XCreateImage() 建立一組 Structure,然後使用 XPutImage() 將該 Structure 和影像資料吃從 XClient 透過 X Protocol(Socket)傳送到 X Server,X Server 再依 XImage 的敘述將圖形畫在視窗上。
XImage 範例程式:
不過,眼尖的人或許已經注意到,此程式完全曝露出 X Client/Server 架構所存在的缺陷,無論要貼什麼圖,都必需先透過 X Protocol 傳送至 X Server,如此大量的資料複製,當然取而代之的就是效能低落。一種改善效能的方法就是使用 Shm(Shared Memory),使 X Client 和 X Server 共享一塊記憶體,讓原先的大量複製資料,改由傳記憶體位置取代,為此,X 就支援了 XShm Extension 來實作此種方法。
XShm Extension 所提供能函式與原生的 XImage 相關函式相差不大,這邊用另一個範例程式做說明:
大體上,主要就是 XCreateImage 換成 XShmPutImage,XPutImage 換成 XShmPutImage,更多資料可以參考 XFree86 MIT-SHM 文件:
http://www.xfree86.org/current/mit-shm.html
這裡記載著一個簡單的範例程式,用來說明 X 如何利用 XImage 做貼圖運算,其主要是將 buffer(100x100x32bits 的影像)畫在視窗上,該 buffer 可以是讀取圖檔或是使用各種資料來源,為一塊記憶體。此程式將會用 XCreateImage() 建立一組 Structure,然後使用 XPutImage() 將該 Structure 和影像資料吃從 XClient 透過 X Protocol(Socket)傳送到 X Server,X Server 再依 XImage 的敘述將圖形畫在視窗上。
XImage 範例程式:
void main(void) { Window win; Display display = XOpenDisplay(getenv("DISPLAY")); XImage *ximage; unsigned char *buffer; /* Initial Window */ win = XCreateSimpleWindow(display, RootWindow(display, DefaultScreen(display)), 0, 0, 100, 100, 0, BlackPixel(display, DefaultScreen(display)), BlackPixel(display, DefaultScreen(display))); XMapWindow(display, win); XSync(display, False); /* Allocate image memory for 100x100x32bits */ buffer = (unsigned char *)malloc(sizeof(char) * 100 * 100 * 4); /* Create XImage structure and map image memory on it */ ximage = XCreateImage(display, DefaultVisual(display, 0), DefaultDepth(display, 0), ZPixmap, 0, buffer, 100, 100, 32, 0); /* Put XImage into X Server to display */ XPutImage(display, window, DefaultGC(display, 0), ximage, 0, 0, 0, 0, 100, 100); /* Loop */ while(1) {}; /* Release */ XDestroyImage(ximage); XCloseDisplay(display); }
不過,眼尖的人或許已經注意到,此程式完全曝露出 X Client/Server 架構所存在的缺陷,無論要貼什麼圖,都必需先透過 X Protocol 傳送至 X Server,如此大量的資料複製,當然取而代之的就是效能低落。一種改善效能的方法就是使用 Shm(Shared Memory),使 X Client 和 X Server 共享一塊記憶體,讓原先的大量複製資料,改由傳記憶體位置取代,為此,X 就支援了 XShm Extension 來實作此種方法。
XShm Extension 所提供能函式與原生的 XImage 相關函式相差不大,這邊用另一個範例程式做說明:
void main(void) { Window win; Display display = XOpenDisplay(getenv("DISPLAY")); XImage *ximage; unsigned char *buffer; XShmSegmentInfo shminfo; /* XShm */ XShmQueryExtension(display); /* Initial Window */ win = XCreateSimpleWindow(display, RootWindow(display, DefaultScreen(display)), 0, 0, 100, 100, 0, BlackPixel(display, DefaultScreen(display)), BlackPixel(display, DefaultScreen(display))); XMapWindow(display, win); XSync(display, False); /* Allocate image memory for 100x100x32bits */ buffer = (unsigned char *)malloc(sizeof(char) * 100 * 100 * 4); /* Create XImage structure and map image memory on it */ ximage = XShmCreateImage(display, DefaultVisual(display, 0), DefaultDepth(display, 0), ZPixmap, 0, &shminfo, 100, 100); /* Setting SHM */ shminfo.shmid = shmget(IPC_PRIVATE, 100 * 100 * 4, IPC_CREAT | 0777); if (shminfo.shmid < 0) exit(-1); shminfo.shmaddr = ximage->data = (unsigned char *)shmat(shminfo.shmid, 0, 0); if(shminfo.shmaddr == (char *) -1) exit(-1); shminfo.readOnly = False; XShmAttach(display, &shminfo); /* Put XImage into X Server to display */ XShmPutImage(display, win, DefaultGC(display, 0), ximage, 0, 0, 0, 0, 100, 100, False); XFlush(display); /* Loop */ while(1) {}; /* Release */ XDestroyImage(ximage); XCloseDisplay(display); }
大體上,主要就是 XCreateImage 換成 XShmPutImage,XPutImage 換成 XShmPutImage,更多資料可以參考 XFree86 MIT-SHM 文件:
http://www.xfree86.org/current/mit-shm.html
上周我為 MadButterfly 加上 xshm 的支援之後,動畫的反應快了很多。另外 X server 的 loading 也降低非常多。後來我觀察 firefox,發覺也是用相同的方式。不過 SysV 的 share memory 使用要特別小心,特別是權限和 resource 的刪除。額外的好處是,你可以透過第三方程式去讀取 X client 和 server 之間傳送的畫面。
回覆刪除