據說qemu的gpu的實作,運作起來非常慢。是以android emulator提供了一種use host gpu的方式,guest os可以使用host機器的opengl庫去畫圖,速度快很多。
guest os把畫圖的指令通過pipe傳遞給emulator(encode, send via pipe, decode),然後emulator将opengles的畫圖指令轉為opengl的畫圖指令(translate),并執行。
老規矩,看文檔,opengles是使用tcp實作的,tcp也是pipe service
<a target="_blank" href="http://androidxref.com/5.1.0_r1/xref/external/qemu/docs/ANDROID-QEMU-PIPE.TXT#306">ANDROID-QEMU-PIPE.TXT:306</a>
初始化代碼如下,初始化了opengles,tcp和unix三種
netPipe_initUnix or netPipe_initTcp建立了opengles pipe service和emulator中畫圖服務端的socket連接配接
netPipe_initUnix or netPipe_initTcp都會調用到netPipe_initFromAddress函數,裡面的loopIo_init和asyncConnector_init需要注意一下,大概意思是有個公用的循環,使用LoopIo把fd包裝起來,循環裡面會檢查哪些fd可讀,或者可寫,并且調用callback函數netPipe_io_func
netPipe_io_func是剛才那個callback函數,就是用來喚醒等待讀寫的線程的,如果未連接配接,那麼會先連接配接一下(connect)
通過/dev/qemu_pipe寫東西,最終會調用到netPipe_sendBuffers函數(evil switch in pipeConnector_sendBuffers),然後通過剛才建立的socket發送給畫圖服務端
從/dev/qemu_pipe讀東西,最終會調用到netPipe_recvBuffers函數(evil switch in pipeConnector_sendBuffers),然後通過剛才建立的socket從畫圖服務端接收資料
netPipe_poll調用loopIo_poll判斷是否POLLIN, POLLOUT
netPipe_wakeOn設定想等待什麼事件
老規矩,先看文檔,文檔在模拟器的repo中可以找到,我在android的repo裡面沒找到
重點看external/qemu/distrib/android-emugl/DESIGN
libEGL.so、libGLESv1_CM.so和libGLESv2.so是純軟體方面的通用的代碼,在模拟器上不需要任何特殊的處理
libEGL.so會根據egl.cfg的配置,dlopen幾個庫,在模拟器上是libEGL_emulation.so、libGLESv1_CM_emulation.so和libGLESv2_emulation.so,這幾個庫是硬體相關的
libEGL_emulation.so、libGLESv1_CM_emulation.so和libGLESv2_emulation.so對應了GUEST SYSTEM LIBRARIES,它們的函數最終都會通過<function_name>_enc進行encode,然後通過opengles pipe serice給到emulator,emulator再通過tcp socket發送給畫圖服務端,服務端的libOpenglRender.so使用幾個decode的庫去進行decode,然後分發給libEGL_translator.so、libGLES_CM_translator.so和libGLESv2_translator.so,它們将opengles的調用轉為opengl的調用,然後使用host系統的opengl庫去執行
qemu和ui是兩個不同的程序,ui裡面的是畫圖的服務端,qemu裡面的是socket client,也就是opengles pipe service中建立的socket連接配接。
再看看external/qemu/docs/GPU-EMULATION.TXT