Merge "emulator: opengl: add design document for emulation implementation."
This commit is contained in:
committed by
Android (Google) Code Review
commit
a8f182c105
593
tools/emulator/opengl/DESIGN
Normal file
593
tools/emulator/opengl/DESIGN
Normal file
@@ -0,0 +1,593 @@
|
||||
Android Hardware OpenGLES emulation design overview
|
||||
===================================================
|
||||
|
||||
Introduction:
|
||||
-------------
|
||||
|
||||
Hardware GLES emulation in the Android platform is implemented with a mix
|
||||
of components, which are:
|
||||
|
||||
- Several host "translator" libraries. They implement the EGL, GLES 1.1 and
|
||||
GLES 2.0 ABIs defined by Khronos, and translate the corresponding function
|
||||
calls into calls to the appropriate desktop APIs, i.e.:
|
||||
|
||||
- Xgl (Linux), AGL (OS X) or WGL (Windows) for EGL
|
||||
- desktop GL 2.0 for GLES 1.1 and GLES 2.0
|
||||
|
||||
_________ __________ __________
|
||||
| | | | | | HOST
|
||||
|TRANSLATOR |TRANSLATOR| |TRANSLATOR| HOST
|
||||
| EGL | | GLES 1.1 | | GLES 2.0 | TRANSLATOR
|
||||
|_________| |__________| |__________| LIBRARIES
|
||||
| | |
|
||||
- - - | - - - - - - - - - | - - - - - - - - - | - - - - -
|
||||
| | |
|
||||
____v____ ____v_____ _____v____ HOST
|
||||
| | | | | | SYSTEM
|
||||
| Xgl | | GL 2.0 | | GL 2.0 | LIBRARIES
|
||||
|_________| |__________| |__________|
|
||||
|
||||
|
||||
|
||||
- Several system libraries inside the emulated guest system that implement
|
||||
the same EGL / GLES 1.1 and GLES 2.0 ABIs.
|
||||
|
||||
They collect the sequence of EGL/GLES function calls and translate then
|
||||
into a custom wire protocol stream that is sent to the emulator program
|
||||
through a high-speed communication channel called a "QEMU Pipe".
|
||||
|
||||
For now, all you need to know is that the pipe is implemented with a
|
||||
custom kernel driver, and provides for _very_ fast bandwidth. All read()
|
||||
and writes() from/to the pipes are essentially instantaneous from the
|
||||
guest's point of view.
|
||||
|
||||
|
||||
_________ __________ __________
|
||||
| | | | | |
|
||||
|EMULATION| |EMULATION | |EMULATION | GUEST
|
||||
| EGL | | GLES 1.1 | | GLES 2.0 | SYSTEM
|
||||
|_________| |__________| |__________| LIBRARIES
|
||||
| | |
|
||||
- - - | - - - - - - - - - | - - - - - - - - - | - - - - -
|
||||
| | |
|
||||
____v____________________v____________________v____ GUEST
|
||||
| | KERNEL
|
||||
| QEMU PIPE |
|
||||
|___________________________________________________|
|
||||
|
|
||||
- - - - - - - - - - - - - -|- - - - - - - - - - - - - - - -
|
||||
|
|
||||
v
|
||||
EMULATOR
|
||||
|
||||
- Specific code inside the emulator program that is capable of transmitting
|
||||
the wire protocol stream to a special rendering library or process (called
|
||||
the "renderer" here), which understands the format.
|
||||
|
||||
|
|
||||
| PROTOCOL BYTE STREAM
|
||||
_____v_____
|
||||
| |
|
||||
| EMULATOR |
|
||||
|___________|
|
||||
|
|
||||
| UNMODIFIED PROTOCOL BYTE STREAM
|
||||
_____v_____
|
||||
| |
|
||||
| RENDERER |
|
||||
|___________|
|
||||
|
||||
|
||||
- The renderer decodes the EGL/GLES commands from the wire
|
||||
protocol stream, and dispatches them to the translator libraries
|
||||
appropriately.
|
||||
|
||||
|
|
||||
| PROTOCOL BYTE STREAM
|
||||
_____v_____
|
||||
| |
|
||||
| RENDERER |
|
||||
|___________|
|
||||
| | |
|
||||
+-----------------+ | +-----------------+
|
||||
| | |
|
||||
____v____ ___v______ ____v_____
|
||||
| | | | | | HOST
|
||||
|TRANSLATOR |TRANSLATOR| |TRANSLATOR| HOST
|
||||
| EGL | | GLES 1.1 | | GLES 2.0 | TRANSLATOR
|
||||
|_________| |__________| |__________| LIBRARIES
|
||||
|
||||
|
||||
|
||||
- In reality, the protocol stream flows in both directions, even though most
|
||||
of the commands result in data going from the guest to the host. A complete
|
||||
picture of the emulation would thus be:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_________ __________ __________
|
||||
| | | | | |
|
||||
|EMULATION| |EMULATION | |EMULATION | GUEST
|
||||
| EGL | | GLES 1.1 | | GLES 2.0 | SYSTEM
|
||||
|_________| |__________| |__________| LIBRARIES
|
||||
^ ^ ^
|
||||
| | |
|
||||
- - - | - - - - - - - - - | - - - - - - - - - | - - - - -
|
||||
| | |
|
||||
____v____________________v____________________v____ GUEST
|
||||
| | KERNEL
|
||||
| QEMU PIPE |
|
||||
|___________________________________________________|
|
||||
^
|
||||
|
|
||||
- - - - - - - - - - - - - -|- - - - - - - - - - - - - - - -
|
||||
|
|
||||
| PROTOCOL BYTE STREAM
|
||||
_____v_____
|
||||
| |
|
||||
| EMULATOR |
|
||||
|___________|
|
||||
^
|
||||
| UNMODIFIED PROTOCOL BYTE STREAM
|
||||
_____v_____
|
||||
| |
|
||||
| RENDERER |
|
||||
|___________|
|
||||
^ ^ ^
|
||||
| | |
|
||||
+-----------------+ | +-----------------+
|
||||
| | |
|
||||
____v____ ___v______ ____v_____
|
||||
| | | | | |
|
||||
|TRANSLATOR |TRANSLATOR| |TRANSLATOR| HOST
|
||||
| EGL | | GLES 1.1 | | GLES 2.0 | TRANSLATOR
|
||||
|_________| |__________| |__________| LIBRARIES
|
||||
^ ^ ^
|
||||
| | |
|
||||
- - - | - - - - - - - - - | - - - - - - - - - | - - - - -
|
||||
| | |
|
||||
____v____ ____v_____ _____v____ HOST
|
||||
| | | | | | SYSTEM
|
||||
| Xgl | | GL 2.0 | | GL 2.0 | LIBRARIES
|
||||
|_________| |__________| |__________|
|
||||
|
||||
(NOTE: 'Xgl' is for Linux only, replace 'AGL' on OS X, and 'WGL' on Windows).
|
||||
|
||||
|
||||
Note that, in the above graphics, only the host system libraries at the bottom
|
||||
are _not_ provided by Android.
|
||||
|
||||
|
||||
Design Requirements:
|
||||
--------------------
|
||||
|
||||
The above design comes from several important requirements that were decided
|
||||
early in the project:
|
||||
|
||||
1 - The ability to run the renderer in a separate process from the emulator
|
||||
itself is important.
|
||||
|
||||
For various practical reasons, we plan to completely separate the core QEMU
|
||||
emulation from the UI window by using two distinct processes. As such, the
|
||||
renderer will be implemented as a library inside the UI program, but will
|
||||
need to receive protocol bytes from the QEMU process.
|
||||
|
||||
The communication channel will be either a fast Unix socket or a Win32
|
||||
named pipe between these two. A shared memory segment with appropriate
|
||||
synchronization primitives might also be used if performance becomes
|
||||
an issue.
|
||||
|
||||
This explains why the emulator doesn't alter or even try to parse the
|
||||
protocol byte stream. It only acts as a dumb proxy between the guest
|
||||
system and the renderer. This also avoids adding lots of GLES-specific
|
||||
code inside the QEMU code base which is terribly complex.
|
||||
|
||||
2 - The ability to use vendor-specific desktop EGL/GLES libraries is
|
||||
important.
|
||||
|
||||
GPU vendors like NVidia, AMD or ARM all provide host versions of the
|
||||
EGL/GLES libraries that emulate their respectivie embedded graphics
|
||||
chipset.
|
||||
|
||||
The renderer library can be configured to use these instead of the
|
||||
translator libraries provided with this project. This can be useful to
|
||||
more accurately emulate the behaviour of specific devices.
|
||||
|
||||
Moreover, these vendor libraries typically expose vendor-specific
|
||||
extensions that are not provided by the translator libraries. We cannot
|
||||
expose them without modifying our code, but it's important to be able
|
||||
to do so without too much pain.
|
||||
|
||||
|
||||
Code organization:
|
||||
------------------
|
||||
|
||||
All source code for the components above is spread over multiple directories
|
||||
in the Android source trees:
|
||||
|
||||
- The emulator sources are under $ANDROID/external/qemu, which we'll
|
||||
call $QEMU in the rest of this document.
|
||||
|
||||
- The guest and system libraries are under
|
||||
$ANDROID/development/tools/emulator/opengl, which we'll call $EMUGL
|
||||
|
||||
- The QEMU Pipe kernel driver is under $KERNEL/drivers/misc/qemupipe
|
||||
|
||||
Where $ANDROID is the top of the open-source Android source tree, and
|
||||
$KERNEL is the top of the qemu-specific kernel source tree (using one
|
||||
of the android-goldfish-xxxx branches here).
|
||||
|
||||
The emulator sources related to this projects are:
|
||||
|
||||
$QEMU/hw/goldfish_pipe.c -> implement QEMU pipe virtual hardware
|
||||
$QEMU/hw/opengles.c -> implement GLES initialization
|
||||
$QEMU/hw/hw-pipe-net.c -> implements the communication channel
|
||||
between the QEMU Pipe and the renderer library
|
||||
|
||||
The other sources are:
|
||||
|
||||
$EMUGL/system -> system libraries
|
||||
$EMUGL/host -> host libraries (translator + renderer)
|
||||
$EMUGL/shared -> shared libraries, used both in the guest and the host
|
||||
$EMUGL/tests -> various test programs
|
||||
|
||||
|
||||
Translator libraries:
|
||||
---------------------
|
||||
|
||||
There are three translator host libraries provided by this project:
|
||||
|
||||
libEGL_translator -> EGL 1.2 translation
|
||||
libGLES_CM_translator -> GLES 1.1 translation
|
||||
libGLES_V2_translator -> GLES 2.0 translation
|
||||
|
||||
The full name of the library will depend on the host system.
|
||||
For simplicity, only the library name suffix will change (i.e. the
|
||||
'lib' prefix is not dropped on Windows), i.e.:
|
||||
|
||||
libEGL_translator.so -> for Linux
|
||||
libEGL_translator.dylib -> for OS X
|
||||
libEGL_translator.dll -> for Windows
|
||||
|
||||
The source code for these libraries is located under the following
|
||||
path in the Android source tree:
|
||||
|
||||
$EMUGL/host/libs/Translator/EGL
|
||||
$EMUGL/host/libs/Translator/GLES_CM
|
||||
$EMUGL/host/libs/Translator/GLES_V2
|
||||
|
||||
The translator libraries also use a common routines defined under:
|
||||
|
||||
$EMUGL/host/libs/Translator/GLcommon
|
||||
|
||||
|
||||
Wire Protocol Overiew:
|
||||
----------------------
|
||||
|
||||
The "wire protocol" is implemented as follows:
|
||||
|
||||
- EGL/GLES function calls are described through several "specification"
|
||||
files, which describes the types, function signatures and various
|
||||
attributes for each one of them.
|
||||
|
||||
- These files are read by a tool called "emugen" which generates C
|
||||
source files and headers based on the specification. These correspond
|
||||
to both encoding, decoding and "wrappers" (more on this later).
|
||||
|
||||
- System "encoder" static libraries are built using some of these generated
|
||||
files. They contain code that can serialize EGL/GLES calls into simple
|
||||
byte messages and send it through a generic "IOStream" object.
|
||||
|
||||
- Host "decoder" static libraries are also built using some of these
|
||||
generated files. Their code retrieves byte messages from an "IOStream"
|
||||
object, and translates them into function callbacks.
|
||||
|
||||
IOStream abstraction:
|
||||
- - - - - - - - - - -
|
||||
|
||||
The "IOStream" is a very simple abstract class used to send byte messages
|
||||
both in the guest and host. It is defined through a shared header under
|
||||
$EMUGL/host/include/libOpenglRender/IOStream.h
|
||||
|
||||
Note that despite the path, this header is included by *both* host and guest
|
||||
source code. The main idea around IOStream's design is that to send a message,
|
||||
one does the following:
|
||||
|
||||
1/ call stream->allocBuffer(size), which returns the address of a
|
||||
memory buffer of at least 'size' bytes.
|
||||
|
||||
2/ write the content of the serialized command (usually a header + some
|
||||
payload) directly into the buffer
|
||||
|
||||
3/ call stream->commitBuffer() to send it.
|
||||
|
||||
Alternatively, one can also pack several commands into a single buffer with
|
||||
stream->alloc() and stream->flush(), as in:
|
||||
|
||||
1/ buf1 = stream->alloc(size1)
|
||||
2/ write first command bytes into buf1
|
||||
3/ buf2 = stream->alloc(size2)
|
||||
4/ write second command bytes into buf2
|
||||
5/ stream->flush()
|
||||
|
||||
Finally, there are also explict read/write methods like stream->readFully()
|
||||
or stream->writeFully() which can be used when you don't want an intermediate
|
||||
buffer. This is used in certain cases by the implementation, e.g. to avoid
|
||||
an intermediate memory copy when sending texture data from the guest to the
|
||||
host.
|
||||
|
||||
The host IOStream implementations are under $EMUGL/shared/OpenglCodecCommon/,
|
||||
see in particular:
|
||||
|
||||
$EMUGL/shared/OpenglCodecCommon/TcpStream.cpp -> using local TCP sockets
|
||||
$EMUGL/shared/OpenglCodecCommon/UnixStream.cpp -> using Unix sockets
|
||||
$EMUGL/shared/OpenglCodecCommon/Win32PipeStream.cpp -> using Win32 named pipes
|
||||
|
||||
The guest IOStream implementation uses the TcpStream.cpp above, as well as
|
||||
an alternative QEMU-specific source:
|
||||
|
||||
$EMUGL/system/OpenglSystemCommon/QemuPipeStream.cpp -> uses QEMU pipe from the guest
|
||||
|
||||
The QEMU Pipe implementation is _significantly_ faster (about 20x) due to
|
||||
several reasons:
|
||||
|
||||
- all succesful read() and write() operations through it are instantaneous
|
||||
from the guest's point of view.
|
||||
|
||||
- all buffer/memory copies are performed directly by the emulator, and thus
|
||||
much faster than performing the same thing inside the kernel with emulated
|
||||
ARM instructions.
|
||||
|
||||
- it doesn't need to go through a kernel TCP/IP stack that will wrap the
|
||||
data into TCP/IP/MAC packets, send them to an emulated ethernet device,
|
||||
which is itself connected to an internal firewall implementation that
|
||||
will unwrap the packets, re-assemble them, then send them through BSD
|
||||
sockets to the host kernel.
|
||||
|
||||
However, would it be necessary, you could write a guest IOStream implementation
|
||||
that uses a different transport. If you do, please look at
|
||||
$EMUGL/system/OpenglCodecCommon/HostConnection.cpp which contains the code
|
||||
used to connect the guest to the host, on a per-thread basis.
|
||||
|
||||
|
||||
Source code auto-generation:
|
||||
- - - - - - - - - - - - - -
|
||||
|
||||
The 'emugen' tool is located under $EMUGL/host/tools/emugen. There is a README
|
||||
file that explains how it works.
|
||||
|
||||
You can also look at the following specifications files:
|
||||
|
||||
For GLES 1.1:
|
||||
$EMUGL/system/GLESv1_enc/gl.types
|
||||
$EMUGL/system/GLESv1_enc/gl.in
|
||||
$EMUGL/system/GLESv1_enc/gl.attrib
|
||||
$EMUGL/system/GLESv1_enc/gl.addon
|
||||
|
||||
For GLES 2.0:
|
||||
$EMUGL/system/GLESv2_enc/gl2.types
|
||||
$EMUGL/system/GLESv2_enc/gl2.in
|
||||
$EMUGL/system/GLESv2_enc/gl2.attrib
|
||||
$EMUGL/system/GLESv2_enc/gl2.addon
|
||||
|
||||
For EGL:
|
||||
$EMUGL/system/renderControl_enc/renderControl.types
|
||||
$EMUGL/system/renderControl_enc/renderControl.in
|
||||
$EMUGL/system/renderControl_enc/renderControl.attrib
|
||||
$EMUGL/system/renderControl_enc/renderControl.addon
|
||||
|
||||
Note that the EGL specification files are under a directory named
|
||||
"renderControl_enc" and have filenames that begin with "renderControl"
|
||||
|
||||
This is mainly for historic reasons now, but is also related to the fact that
|
||||
this part of the wire protocol contains support functions/calls/specifications
|
||||
that are not part of the EGL specification itself, but add a few features
|
||||
required to make everything works. For example, they have calls related to
|
||||
the "gralloc" system library module used to manage graphics surfaces at a
|
||||
lower level than EGL.
|
||||
|
||||
Generally speaking, guest encoder sources are located under directories
|
||||
named $EMUGL/system/<name>_enc/, while the corresponding host decoder
|
||||
sources will be under $EMUGL/host/libs/<name>_dec/
|
||||
|
||||
However, all these sources use the same spec files located under the
|
||||
encoding directories. The decoders may even need to include a few
|
||||
non-auto-generated header files from the encoder directories.
|
||||
|
||||
|
||||
|
||||
System libraries:
|
||||
-----------------
|
||||
|
||||
Meta EGL/GLES system libraries, and egl.cfg:
|
||||
- - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
It is important to understand that the emulation-specific EGL/GLES libraries
|
||||
are not directly linked by applications at runtime. Instead, the system
|
||||
provides a set of "meta" EGL/GLES libraries that will load the appropriate
|
||||
hardware-specific libraries on first use.
|
||||
|
||||
More specifically, the system libEGL.so contains a "loader" which will try
|
||||
to load:
|
||||
|
||||
- hardware-specific EGL/GLES libraries
|
||||
- the software-based rendering libraries (called "libagl")
|
||||
|
||||
The system libEGL.so is also capable of merging the EGL configs of both the
|
||||
hardware and software libraries transparently to the application. The system
|
||||
libGLESv1_CM.so and libGLESv2.so, work with it to ensure that the thread's
|
||||
current context will be linked to either the hardware or software libraries
|
||||
depending on the config selected.
|
||||
|
||||
For the record, the loader's source code in under
|
||||
frameworks/base/opengl/libs/EGL/Loader.cpp. It depends on a file named
|
||||
/system/lib/egl/egl.cfg which must contain two lines that look like:
|
||||
|
||||
0 1 <name>
|
||||
0 0 android
|
||||
|
||||
The first number in each line is a display number, and must be 0 since the
|
||||
system's EGL/GLES libraries don't support anything else.
|
||||
|
||||
The second number must be 1 to indicate hardware libraries, and 0 to indicate
|
||||
a software one. The line corresponding to the hardware library, if any, must
|
||||
always appear before the one for the software library.
|
||||
|
||||
The third field is a name corresponding to a shared library suffix. It really
|
||||
means that the corresponding libraries will be named libEGL_<name>.so,
|
||||
libGLESv1_CM_<name>.so and libGLESv2_<name>.so. Moreover these libraries must
|
||||
be placed under /system/lib/egl/
|
||||
|
||||
The name "android" is reserved for the system software renderer.
|
||||
|
||||
The egl.cfg that comes with this project uses the name "emulation" for the
|
||||
hardware libraries. This means that it provides an egl.cfg file that contains
|
||||
the following lines:
|
||||
|
||||
0 1 emulation
|
||||
0 0 android
|
||||
|
||||
See $EMUGL/system/egl/egl.cfg and more generally the following build files:
|
||||
|
||||
$EMUGL/system/egl/Android.mk
|
||||
$EMUGL/system/GLESv1/Android.mk
|
||||
$EMUGL/system/GLESv2/Android.mk
|
||||
|
||||
to see how the libraries are named and placed under /system/lib/egl/ by the
|
||||
build system.
|
||||
|
||||
|
||||
Emulation libraries:
|
||||
- - - - - - - - - - -
|
||||
|
||||
The emulator-specific libraries are under the following:
|
||||
|
||||
$EMUGL/system/egl/
|
||||
$EMUGL/system/GLESv1/
|
||||
$EMUGL/system/GLESv2/
|
||||
|
||||
The code for GLESv1 and GLESv2 is pretty small, since it mostly link against
|
||||
the static encoding libraries.
|
||||
|
||||
The code for EGL is a bit more complex, because it needs to deal with
|
||||
extensions dynamically. I.e. if an extension is not available on the host
|
||||
it shouldn't be exposed by the library at runtime. So the EGL code queries
|
||||
the host for the list of available extensions in order to return them to
|
||||
clients. Similarly, it must query the list of valid EGLConfigs for the
|
||||
current host system.
|
||||
|
||||
|
||||
"gralloc" module implementation:
|
||||
- - - - - - - - - - - - - - - - -
|
||||
|
||||
In addition to EGL/GLES libraries, the Android system requires a
|
||||
hardware-specific library to manage graphics surfaces at a level lower than
|
||||
EGL. This library must be what is called in Android land as a "HAL module".
|
||||
|
||||
A "HAL module" must provide interfaces defined by Android's HAL
|
||||
(Hardware Abstraction Library). These interface definitions can be found
|
||||
under $ANDROID/hardware/libhardware/include/
|
||||
|
||||
Of all possible HAL modules, the "gralloc" one is used by the system's
|
||||
SurfaceFlinger to allocate framebuffers and other graphics memory regions,
|
||||
as well as eventually lock/unlock/swap them when needed.
|
||||
|
||||
The code under $EMUGL/system/gralloc/ implements the module required by the
|
||||
GLES emulation project. It's not very long, but there are a few things to
|
||||
notice here:
|
||||
|
||||
- first, it will probe the guest system to determine if the emulator that
|
||||
is running the virtual device really supports GPU emulation. In certain
|
||||
circumstances this may not be possible.
|
||||
|
||||
If this is the case, then the module will redirect all calls to the
|
||||
"default" gralloc module that is normally used by the system when
|
||||
software-only rendering is enabled.
|
||||
|
||||
The probing happens in the function "fallback_init" which gets called
|
||||
when the module is first opened. This initializes the 'sFallback' variable
|
||||
to a pointer to the default gralloc module when required.
|
||||
|
||||
- second, this module is used by SurfaceFlinger to display "software surfaces",
|
||||
i.e. those that are backed by system memory pixel buffers, and written to
|
||||
directly through the Skia graphics library (i.e. the non-accelerated ones).
|
||||
|
||||
the default module simply copies the pixel data from the surface to the
|
||||
virtual framebuffer i/o memory, but this project's gralloc module sends it
|
||||
to the renderer through the QEMU Pipe instead.
|
||||
|
||||
It turns out that this results in _faster_ rendering/frame-rates overall,
|
||||
because memory copies inside the guest are slow, while QEMU pipe transfers
|
||||
are done directly in the emulator.
|
||||
|
||||
|
||||
Host Renderer:
|
||||
--------------
|
||||
|
||||
The host renderer library is located under $EMUGL/host/libs/libOpenglRender,
|
||||
and it provides an interface described by the headers under
|
||||
$EMUGL/host/include/libOpenglRender/render_api.h (e.g. for use by the emulator).
|
||||
|
||||
In a nutshell, the rendering library is responsible for the following:
|
||||
|
||||
- Providing a virtual off-screen video surface where everything will get
|
||||
rendered at runtime. Its dimensions are fixed by the call to
|
||||
initOpenglRender() that must happen just after the library is
|
||||
initialized.
|
||||
|
||||
- Provide a way to display the virtual video surface on a host application's
|
||||
UI. This is done by calling createOpenGLSubWindow() which takes as argument
|
||||
the window ID or handle of a parent window, some display dimensions and
|
||||
a rotation angle. This allows the surface to be scaled/rotated when it is
|
||||
displayed, even if the dimensions of the video surface do not change.
|
||||
|
||||
- Provide a way to listen to incoming EGL/GLES commands from the guest.
|
||||
This is done by providing a so-called "port number" to initOpenglRender().
|
||||
|
||||
By default, the port number corresponds to a local TCP port number that the
|
||||
renderer will bind to and listen. Every new connection to this port will
|
||||
correspond to the creation of a new guest host connection, each such
|
||||
connection corresponding to a distinct thread in the guest system.
|
||||
|
||||
For performance reasons, it is possible to listen to either Unix sockets
|
||||
(on Linux and OS X), or to a Win32 named pipe (on Windows). To do so, one
|
||||
had to call setStreamType() between library initialization
|
||||
(i.e. initLibrary()) and construction (i.e. initOpenglRender()).
|
||||
|
||||
Note that in these modes, the port number is still used to differentiate
|
||||
between several emulator instances. These details are normally handled by
|
||||
the emulator code so you shouldn't care too much.
|
||||
|
||||
Note that an earlier version of the interface allowed a client of the renderer
|
||||
library to provide its own IOStream implementation. However, this wasn't very
|
||||
convenient for a number of reasons. This maybe something that could be done
|
||||
again if it makes sense, but for now the performance numbers are pretty good.
|
||||
|
||||
|
||||
Host emulator:
|
||||
--------------
|
||||
|
||||
The code under $QEMU/android/opengles.c is in charge of dynamically loading
|
||||
the rendering library and initializing / constructing it properly.
|
||||
|
||||
QEMU pipe connections to the 'opengles' service are piped through the code
|
||||
in $QEMU/android/hw-pipe-net.c. Look for the openglesPipe_init() function,
|
||||
which is in charge of creating a connection to the renderer library
|
||||
(either through a TCP socket, or a Unix pipe depending on configuration.
|
||||
support for Win32 named pipes hasn't been implemented yet in the emulator)
|
||||
whenever a guest process opens the "opengles" service through /dev/qemu_pipe.
|
||||
|
||||
There is also some support code for the display of the GLES framebuffer
|
||||
(through the renderer library's subwindow) under $QEMU/skin/window.
|
||||
|
||||
Note that at the moment, scaling and rotation are supported. However,
|
||||
brightness emulation (which used to modify the pixel values from the
|
||||
hardware framebuffer before displaying them) doesn't work.
|
||||
|
||||
Another issue is that it is not possible to display anything on top of the
|
||||
GL subwindow at the moment. E.g. this will obscure the emulated trackball
|
||||
image (that is normally toggled with Ctrl-T during emulation, or enabled
|
||||
by pressing the Delete key).
|
||||
|
||||
Reference in New Issue
Block a user