EGLDevice¶
This topic describes EGL™ mechanisms that you can use to render 3D images on a pure EGL display. Such a display does not use a window system.
EGLDevice¶
EGLDevice provides a mechanism to access graphics functionality in the absence of or without reference to a native window system. It is a method to initialize EGL displays and surfaces directly on top of GPUs/devices rather than native window system objects. It is a cross-platform method to discover media devices like displays, GPUs, etc. The set of EGLDevice extensions boot strap EGL, without the use of any native APIs.
EGLOutput¶
EGLOutput is to graphical outputs what EGLDevice is to devices. It allows enumeration of outputs on a device. EGLOutput allows rendering directly to a screen in the absence of a window system. Additionally, it allows applications to bypass native window systems for direct rendering. It defines certain EGL resources for referencing display control hardware associated with an EGL device. EGLOutput provides a binding between GL, NVIDIA® CUDA®, and multimedia rendering and the display output. In a typical Embedded setting, the outputs are often initialized to a fixed state at system startup. But in cases where they are configurable, other interfaces such as DRM must be used.
EGLStream¶
EGLStream is a mechanism to share data efficiently between different APIs without copying data. APIs could be OpenGL®, CUDA, Multimedia, etc. A producer and a consumer are attached to two ends of a stream object:
Producer adds content into the stream.
Consumer retrieves this content.
EGLOutput instances can also be specified as consumers, allowing APIs to direct their output to the screen.
Extensions¶
EGL extensions specify the behavior, procedures, and functions for these EGL mechanisms.
EGLDevice
EGL_EXT_device_base
EGL_EXT_platform_base
EGL_EXT_platform_device
EGLOutput
EGL_EXT_output_base
EGLStream
EGL_KHR_stream
EGL_KHR_stream_producer_eglsurface
EGL_EXT_stream_consumer_egloutput
For a description of these EGL extensions, see:
“EGL and EGL Extensions” in NVIDIA Jetson Linux API Reference
Runtime Configuration¶
The sections below describe runtime configurations.
Conditions Requiring a Stream Surface¶
In the absence of an underlying window system, the stream surface is
necessary for on screen rendering. Stream surfaces behave like any other
EGLSurface. For example, eglSwapBuffers()
must still be called to
indicate the end of a frame. However, stream surfaces are stream
producers, so eglSwapBuffers()
submits rendering to the stream rather
than presenting it to a native window directly. Typically, an EGLOutput
consumer can use any producer attached to the stream but needs a surface
producer when rendering API is OpenGL. For more information, see
Creating a Stream Surface.
A common use case for stream producer surfaces is an application producing display frames using OpenGL, attached as a producer to one end of an EGL stream. The stream consumer on the other end is an EGLOutput layer sending frames directly to a display device.
Implementation¶
The following two sub-sections describe the steps to render to an EGL device using a stream surface.
Rendering to EGLDevice¶
These are the steps to render to an EGL device (more detailed steps follow):
Create an EGL display from an EGL device.
Create an EGL context from the EGL display.
Create an EGL stream producer surface.
Bind a GL context to the stream surface, i.e. make current.
Post the surface contents to the stream using swap buffers.
Creating a Stream Surface¶
Creating a stream surface uses the following functions:
Function |
Extension and Function Description |
---|---|
|
Creates an EGLSurface and connects it as the producer of a stream. |
|
Binds an EGLOutput layer as a stream consumer to send rendering directly to a display device. |
According to the EGL_KHR_stream specification, the EGLStream cannot be used until it has been connected to a consumer and producer. The consumer must be connected before the producer is connected.
To render to an EGLDevice through stream¶
Query EGL extensions with
eglGetProcAddress()
.Query available EGLDevices with
eglQueryDevicesEXT()
.Obtain an EGLDisplay from the EGLDevice with
eglGetPlatformDisplayEXT()
.This step creates an EGLDisplay that does not belong to any native platform.
Initialize EGL with
eglInitialize()
.Set up an EGLOutput. For detailed steps, see Setting Up the Display with DRM.
Select an output.
Can be done by enumerating all outputs and selecting a known index.
Can be done by looking up an output associated with a native (e.g. DRM) screen handle.
If necessary, initialize display settings with native interfaces.
Direct rendering to an EGLOutput.
Create an EGLStream with
eglCreateStreamKHR()
.Connect the output layer to the EGLStream. Bind consumer end of stream to EGLOutput window object with
eglStreamConsumerOutputEXT()
.
Set buffer configurations by choosing an EGLConfig.
Create a stream producer surface to feed the EGLStream with
eglCreateStreamProducerSurfaceKHR()
.Create an EGLContext and make it current by binding it to the stream surface with
eglMakeCurrent()
.Post surface contents to the stream with
eglSwapBuffers()
.
To use an EGLStream in cross-process mode¶
Make the following additions and changes to nvm_eglstream.int:
AddressSpace nvm_eglstream_producer Filename nvm_eglstream_as0 Arguments -producer 0 -f /nfsmount/welcome_animation.264 -standalone 1 MemoryPoolSize 32M ExtendedMemoryPoolSize 64M HeapExtensionReservedSize 64M Language C Task Initial StartIt false StackLength 2M EndTask EndAddressSpace AddressSpace nvm_eglstream_consumer Filename nvm_eglstream_as0 Arguments -consumer 0 -d 2 -standalone 2 MemoryPoolSize 32M ExtendedMemoryPoolSize 64M HeapExtensionReservedSize 64M Language C Task Initial StartIt false StackLength 2M EndTask EndAddressSpace
Rebuild the application.
Load the application binary with the following command:
Load /nfsmount/nvm_eglstream_egldevice
Start the consumer with the following command:
rt nvm_eglstream_consumer Initial
Start the producer with the following command:
rt nvm_eglstream_producer Initial
This procedure enables a video producer and video consumer combination. The same procedure can also be extended for other producer/consumer combinations.
Cross-Process and Cross-Partition EGLStream Applications¶
This release includes the simple cross-process EGLDevice consumer and
producer applications helloconsumer
and helloproducer
. The applications
listen on 127.0.0.1, port 8888 by default. They can be used as
cross-partition applications by passing –-crosspart
or -c
to the
consumer and –-crosspart [<consumer_ip>]
or -c [<consumer_ip>]
to the
producer.
The applications are built into demo_dd
.
To use the applications¶
Load
demo_dd
.Start
helloconsumer
on the target with the following command:rt helloconsumer Initial
Start
helloproducer
on the target with the following command:rt helloproducer Initial
If the applications run correctly, the upper-left corner of display 2 contains a flashing square.
Using EGL_KHR_stream_consumer_gltexture
functionality, the EGLStream can
also be bound to a gltexture consumer (requiring an EGLContext.) The
consumer texture buffer can then be rendered to an EGLSurface, for
example.
For more information, see the man page for EGL_KHR_stream_consumer_gltexture on the Khronos web site.
Connecting a Surface to a Screen¶
You must use an EGLStream to connect a surface (i.e., a stream surface) to a screen. The surface is the stream producer, and the screen is the stream consumer.
eglGetPlatformDisplayEXT()
returns an EGLDisplay handle belonging to a screen as specified by platform argument in the function call.eglMakeCurrent()
attaches an EGL rendering context to draw and read an EGL surface. It also binds a context and a surface to the current rendering thread.Steps 6 through 9 in Creating a Stream Surface are required for connecting a stream surface to a screen.
eglGetPlatformDisplayEXT()
returns a handle to screen.eglMakeCurrent()
binds the handle to the current context and surface.
Setting Up the Display with DRM¶
The Direct Rendering Manager (DRM) is a framework to manage GPUs and displays. Managing connected monitors and displays and changing the current modes is called mode-setting and is one of the functions of DRM. As mentioned in the “If necessary, initialize display settings …” part in Step 5 in Creating a Stream Surface, this native interface can be used to initialize the display setting.
To select an encoder, CRTC, and connector¶
Open a DRM device file with
drmOpen()
.Obtain DRM-KMS resources with
drmModeGetResources()
.(Optional) Get plane information with
drmModeGetPlane()
anddrmModeGetPlaneResources()
.Query the desired connector with
drmModeGetConnector()
.All valid modes for a connector can be retrieved with a call to
drmModeGetConnector()
. Select the mode to be used and save it. The first mode in the list is the default mode with the highest resolution possible and often a suitable choice.If there is already an encoder attached to the connector, choose it with
drmModeGetEncoder()
.If the attached encoder is incompatible with CRTC/plane find another one by iterating over all available encoders.
Select a suitable CRTC.
For each connector, find a CRTC to drive this connector. To find a suitable CRTC, iterate over the list of encoders that are available for each connector. Each encoder contains a list of CRTCs that it can work with and select one of these CRTCs.
Query info for CRTC with
drmModeGetCrtc()
.
If necessary, set the mode with
drmModeSetCrtc()
. Obtain the layer for the plane/CRTC.Use CRTC to drive the selected connector with a call to
drmModeSetCrtc()
.If a plane must be used, set it with
drmModeSetPlane()
.
More information¶
For API details, see “DRM API” in NVIDIA Jetson Linux API Reference.
Ask your NVIDIA Customer Engineer for a sample implementation,
window_egldevice.zip
.
Board-to-Display Connectors¶
For information about the connectors on your platform and the relationship between connectors and displays, see the documentation for your hardware.