113 lines
5.2 KiB
Markdown
113 lines
5.2 KiB
Markdown
# AVDVirglRenderer
|
|
|
|
This project implements an alternative for 'virglrenderer', a part of the
|
|
Virgil 3D GPU project that normally implements the translation from the
|
|
virtio-gpu-3d command stream & tgsi/gallium shaders, to desktop OpenGL.
|
|
|
|
This version of the library keeps translation to a minimum and only works with
|
|
a true EGL/GLES driver implementation on the host. It won't intercept and
|
|
translate shaders, and no part of the GL state machine is processed in the
|
|
emulated guest.
|
|
|
|
The wire protocol used between the virtio-gpu DRM driver and QEMU's
|
|
virtio-gpu-3d device is the same as that used by goldfish (the classic Android
|
|
emulator). Submits (writes) are made with an `DRM_VIRTGPU_EXECBUFFER` call; the
|
|
response comes back through a separate memory mapped buffer. Responses are very
|
|
expensive and are minimized where possible, as they involve a pipeline flush and
|
|
roundtrip to the host.
|
|
|
|
## Structure
|
|
|
|
### [`AVDVirglRenderer`](AVDVirglRenderer.cpp)[](#AVDVirglRenderer)
|
|
|
|
Provides the entrypoints expected by QEMU for its libvirglrenderer integration.
|
|
|
|
This is where contexts, resources and fences are monitored.
|
|
|
|
### [`RenderControl`](RenderControl.cpp) [`Header`](RenderControl.h) [`Decoder`](renderControl_dec)[](#RenderControl)
|
|
|
|
The RenderControl is analogous to EGL on the guest side. It has a similar API to
|
|
EGL, except that not every EGL function can be implemented as one API call, and
|
|
instead multiple RenderControl calls are made. The RenderControl architecture
|
|
was precipitated by goldfish's requirement that EGL window surfaces and images
|
|
would be directly mapped to GL texture names, but in AVDVirglRenderer we
|
|
preserve them as EGL objects on the host side.
|
|
|
|
This component contains a decoder for the wire protocol, and stubs for any
|
|
functions that we do not need to implement. The wire protocol is completely
|
|
unmodified.
|
|
|
|
### [`GLESv1`](GLESv1.cpp) [`Header`](GLESv1.h) [`Decoder`](GLESv1_dec)[](#GLESv1)
|
|
|
|
This component contains a decoder for the wire protocol, and stubs for any
|
|
functions that we do not need to implement. Only the GL ES 1.1 extensions
|
|
implemented by SwiftShader are implemented, and only if they are needed by
|
|
Android. Any extensions provided by the wire protocol that are not supported by
|
|
either are intentionally stubbed.
|
|
|
|
### [`GLESv3`](GLESv3.cpp) [`Header`](GLESv3.h) [`Decoder`](GLESv3_dec)[](#GLESv3)
|
|
|
|
This component contains a decoder for the wire protocol, and stubs for any
|
|
functions that we do not need to implement. Only the core GL ES 3.0 API is
|
|
implemented; no ES 2.0 extensions are supported, unless they are remappable to
|
|
GL ES 3.0 features. GL ES 3.1 is not currently supported. Any extensions
|
|
provided by the wire protocol that are not supported by either Android or
|
|
SwiftShader are intentionally stubbed.
|
|
|
|
Note that we are *not* stubbing ES 3.1 functions; these will crash if called.
|
|
|
|
### [`ChecksumCalculator`](OpenglRenderer/ChecksumCalculator.cpp)[`Header`](ChecksumCalculator.h)[](#ChecksumCalculator)
|
|
|
|
This code was taken from the Android emulator. The header has been slightly
|
|
trimmed but its functionality has not been changed.
|
|
|
|
### [`ChecksumCalculatorThreadInfo`](ChecksumCalculatorThreadInfo.h)[](#ChecksumCalculatorThreadInfo)
|
|
|
|
This header has been added for compatibility with the decoder code generated by
|
|
the `emugen_cuttlefish` tool. Unlike the original implementation, it is not
|
|
thread safe. We do not require thread safety because no decoder state is shared
|
|
between threads in AVDVirglRenderer without its own locking.
|
|
|
|
### [`Context`](Context.h)[](#Context)
|
|
|
|
The Context structure represents a virglrenderer context assigned by QEMU. Each
|
|
time the driver's device node is opened by the guest, a new context is created.
|
|
In the design of AVDVirglRenderer, there are two kinds of context. The first
|
|
kind of context is for `gralloc`, and there is one of these contexts per guest
|
|
process. The second kind of context is per-thread, used by the EGL/GLES
|
|
implementation. This second kind of context can receive 3D commands, which are
|
|
processed in their own thread by AVDVirglRenderer so as to minimize the number
|
|
of synthetic calls we have to make (such as eglMakeCurrent()).
|
|
|
|
### [`Resource`](Resource.h)[](#Resource)
|
|
|
|
The Resource structure represents a virglrenderer resource assigned by QEMU.
|
|
Each time the driver allocates memory through the device driver's interface, a
|
|
new resource is created. Resources can be owned by the kernel (for example, the
|
|
primary framebuffer surfaces), Gralloc (EGL window surfaces or images), or used
|
|
for other purposes such as the Context response buffer and fencing.
|
|
|
|
### [`EglConfig`](EglConfig.h)[](EglConfig)
|
|
|
|
The EglConfig structure maintains a list of available EGLConfigs.
|
|
|
|
### [`EglContext`](EglContext.h)[](EglContext)
|
|
|
|
The EglContext structure maintains a list of active EGLContexts, and decides
|
|
when they can be disposed of.
|
|
|
|
### [`EglImage`](EglImage.h)[](EglImage)
|
|
|
|
The EglImage structure maintains a list of active EGLImageKHRs, and decides
|
|
when they can be disposed of.
|
|
|
|
### [`EglSurface`](EglSurface.h)[](EglSurface)
|
|
|
|
The EglSurface structure maintains a list of active EGLSurfaces, and decides
|
|
when they can be disposed of.
|
|
|
|
### [`EglSync`](EglSync.h)[](EglSync)
|
|
|
|
The EglSync structure maintains a list of active EGLSyncKHRs, and decides
|
|
when they can be disposed of.
|