一、概述
据说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 —— pipe上的另一个service
老规矩,看文档,opengles是使用tcp实现的,tcp也是pipe service
opengles
Connects to the OpenGL ES emulation process. For now, the implementation
is equivalent to tcp:22468, but this may change in the future.
代码是hw-pipe-net.c,需要先看第二篇pipe的实现
初始化代码如下,初始化了opengles,tcp和unix三种
static const GoldfishPipeFuncs openglesPipe_funcs = {
openglesPipe_init,
netPipe_closeFromGuest,
netPipe_sendBuffers,
netPipe_recvBuffers,
netPipe_poll,
netPipe_wakeOn,
NULL, /* we can't save these */
NULL, /* we can't load these */
};
void
android_net_pipes_init(void)
{
Looper* looper = looper_newCore();
goldfish_pipe_add_type( "tcp", looper, &netPipeTcp_funcs );
#ifndef _WIN32
goldfish_pipe_add_type( "unix", looper, &netPipeUnix_funcs );
#endif
goldfish_pipe_add_type( "opengles", looper, &openglesPipe_funcs );
}
int
android_init_opengles_pipes(void)
{
/* TODO: Check that we can load and initialize the host emulation
* libraries, and return -1 in case of error.
*/
_opengles_init = 1;
return 0;
}
openglesPipe_init在guest往/dev/qemu_pipe里面写"opengles"后,由pipeConnector_sendBuffers函数调用,返回一个NetPipe,和CHANNEL一一对应的
netPipe_initUnix or netPipe_initTcp建立了opengles pipe service和emulator中画图服务端的socket连接
static void*
openglesPipe_init( void* hwpipe, void* _looper, const char* args )
{
NetPipe *pipe;
if (!_opengles_init) {
/* This should never happen, unless there is a bug in the
* emulator's initialization, or the system image. */
D("Trying to open the OpenGLES pipe without GPU emulation!");
return NULL;
}
char server_addr[PATH_MAX];
android_gles_server_path(server_addr, sizeof(server_addr));
#ifndef _WIN32
if (android_gles_fast_pipes) {
pipe = (NetPipe *)netPipe_initUnix(hwpipe, _looper, server_addr);
D("Creating Unix OpenGLES pipe for GPU emulation: %s", server_addr);
} else {
#else /* _WIN32 */
{
#endif
/* Connect through TCP as a fallback */
pipe = (NetPipe *)netPipe_initTcp(hwpipe, _looper, server_addr);
D("Creating TCP OpenGLES pipe for GPU emulation!");
}
if (pipe != NULL) {
// Disable TCP nagle algorithm to improve throughput of small packets
socket_set_nodelay(pipe->io->fd);
// On Win32, adjust buffer sizes
#ifdef _WIN32
{
int sndbuf = 128 * 1024;
int len = sizeof(sndbuf);
if (setsockopt(pipe->io->fd, SOL_SOCKET, SO_SNDBUF,
(char*)&sndbuf, len) == SOCKET_ERROR) {
D("Failed to set SO_SNDBUF to %d error=0x%