From: http://blog.csdn.net/lixinye0123/article/details/4225768
Http://lyodev.appspot.com
Chapter 2 EGL Interface
EGL is an interface between OpenGL ES and the underlying native platform Windows system. This chapter mainly describes the egl api of OpenGL ES, how to use it to create context and draw surface, and makes comparative analysis on other Windows APIs for OpenGL, such as WGL and Glx. This chapter covers the following aspects:
L EGL Overview
L EGL main components (display, context, configuration)
L use EGL on BREW and Windows CE
L comparison between EGL and other OpenGL Windows systems
EGL Introduction
EGL is designed to provide platform independence for OpenGL ES. In this chapter, you will learn in detail each egl api and learn about the platform features and restrictions you need to pay attention to when using EGL. OpenGL ES provides an extension mechanism for additional functions and possible platform feature development, but still requires a layer that allows OpenGL ES to interact with the local Windows system and has nothing to do with the platform. OpenGL ES is essentially a state machine of the graphic rendering pipeline, while EGL is an external layer used to monitor these states and maintain the frame buffer and other rendered surfaces. Figure 2-1 is a typical EGL system layout diagram.
The egl windows design is based on the native interface that is familiar to Microsoft Windows (WGL) and Unix (Glx) OpenGL, which is closer to the latter. The OpenGL ES graphics pipeline state is stored in a context managed by EGL. Frame buffers and other surfaces are created, managed, and destroyed through the egl api. EGL also controls and provides access to device display and possible device rendering configurations.
EGL Data Type
EGL contains a set of data types and supports local data types related to a set of platforms. These native data types are defined in the header file of The egl system. Once you understand the differences between these data types, it is easy to use them. In most cases, to ensure portability, developers will try to use abstract data types to avoid using system data types directly. By using the native type defined in EGL, you can run the EGL code you write on any EGL implementation. The native EGL types are described as follows:
LNativedisplaytypeThe Platform displays the data type and identifies the physical screen of the device you are developing.
LNativewindowtypePlatform window data type, which identifies the system Window
LNativepixmaptypeIt can be used as the system image (memory) Data Type of framebuffer. This type is only used for off-screen rendering.
The following code is an example of nativewindowtype definition. This is just an example. The implementations of different platforms vary widely. The key role of using the native type is to abstract these details for developers. Qualcomm uses the idib structure to define the native type, as shown below:
Struct idib {
Aeevtbl (ibitmap) * PVT; // virtual table pointer
Iqueryinterface * ppalettemap; // cache for computed palette mapping info
Byte * pbmp; // pointer to top row
Uint32 * prgb; // palette
Nativecolor nctransparent; // 32-bit native color value
Uint16 CX; // number of pixels in width
Uint16 Cy; // number of pixels in height
Int16 npitch; // offset from one row to the next
Uint16 cntrgb; // Number of palette entries
Uint8 ndepth; // size of pixel in bits
Uint8 ncolorscheme; // idib_colorscheme _... (ie. 5-6-5)
Uint8 reserved [6];
};
In the following section, we will go into more details about the EGL data type. The standard EGL data types are shown in Table 2.1.
Table 2.1 EGL Data Type
Data Type |
Value |
Eglboolean |
Egl_true = 1, egl_false = 0 |
Eglint |
Int Data Type |
Egldisplay |
ID or handle displayed by the System |
Eglconfig |
EGL configuration of Surface |
Eglsurface |
System window or frame buffer handle |
Eglcontext |
OpenGL ES graphic Context |
Nativedisplaytype |
Native system display type |
Nativewindowtype |
Native System window cache type |
Nativepixmaptype |
Native System Frame Buffer |
EGL displays
Egldisplay is a common data type associated with the physical screen of the system. For PC, display is the display handle. Either an embedded system or a PC can have multiple physical display devices. To use the display devices of the system, EGL provides the egldisplay data type and APIs for displaying a group of Operation devices.
The following function prototype is used to obtain native display:
Egldisplay eglgetdisplay (nativedisplaytype display );
The display parameter is the ID value displayed in the native System window. You can useEgl_default_displayParameters. If no available native display ID matches the given display parameter, the function returns egl_no_display without any error status being set.
Because the invalid display value does not have any error status, check the returned value before proceeding.
The following is an example of getting the system display using The egl API:
M_egldisplay = eglgetdisplay (system. Display );
If (m_egldisplay = egl_no_display | eglgeterror ()! = Egl_success ))
Throw error_egl_display;
Initialization
Similar to many windows APIs, EGL needs to be initialized before use, so each egldisplay needs to be initialized before use. When initializing egldisplay, you can get the implementation version number of EGL in the system. Understanding the current version number is very valuable in backward compatibility. Embedded and mobile devices are usually constantly put on the market, so you need to consider that your code will be run in a variety of implementations. By dynamically querying the EGL version number, you can add additional features or runtime environments for the old and new versions of EGL. Based on platform configuration, software development is available to clearly know which APIs are available for access, which will provide maximum portability for your code.
The following is a prototype of the function that initializes EGL:
Eglboolean eglinitialize (egldisplay dpy, eglint * Major, eglint * minor );
Dpy should be a valid egldisplay. When the function returns, major and minor are assigned the current EGL version number. For example, egl1.0, major returns 1, and minor returns 0. It is valid to pass null to major and minor if you do not care about the version number.
The eglquerystring () function is another way to obtain version information and other information. To obtain version information through eglquerystring (), you need to parse the version string. Therefore, it is easier to obtain this information by passing a pointer to the eglinitializ () function. Note that you must use eglinitialize () to initialize egldisplay before calling eglquerystring (). Otherwise, the egl_not_initialized error message is returned.
The following is a function prototype for obtaining string information of The egl version:
Const char * eglquerystring (egldisplay dpy, eglint name );
The parameter name can be egl_vendor, egl_version, or egl_extensions. This function is most commonly used to query which EGL extensions are implemented. All EGL extensions are optional. If you want to use a certain extension feature, check whether the extension has been implemented. If no extension is implemented, a null string is returned. If the given name parameter is invalid, the egl_bad_parameter. error message is returned. EGL configurations
Eglconfigs is a data type used to describe EGL surface configuration information. To get the correct rendering result, the surface format is very important. Depending on the platform, the surface configuration may be limited. For example, a device only supports 16-bit color-depth display, or does not support stencel buffer. There are other functional limitations or differences in accuracy.
The following is a function prototype for obtaining the available EGL configuration information of the system:
Eglboolean eglgetconfigs (egldisplay dpy, eglconfig * configs, eglint config_size, eglint * num_config );
The configs parameter will contain a list of all valid EGL framebuffer configurations on your platform. The total number of supported configurations is returned through num_config. The actual number of returned configs configurations depends on the config_size passed in by the program. If config_size <num_config, not all configuration information will be returned. If you want to obtain all the configurations supported by the system, the best way is to first pass a null configs parameter to eglgetconfig, and num_config will get the total number of configurations supported by the system, use it to allocate the appropriate memory size to configs, and then use the obtained configs to call eglgetconfig.
The following example shows how to use the eglgetconfig () function:
Eglconfig * configs_list;
Eglint num_configs;
// Main display
M_egldisplay = eglgetdisplay (egl_default_display );
If (m_egldisplay = egl_no_display | eglgeterror ()! = Egl_success)
Return false;
If (eglinitialize (m_egldisplay, null, null) = egl_false | eglgeterror ()! = Egl_success)
Return false;
// Find out how many supported ations are supported
If (eglgetconfigs (m_egldisplay, null, 0, & num_configs)
= Egl_false | eglgeterror ()! = Egl_success)
Return false;
Configs_list = malloc (num_configs * sizeof (eglconfig ));
If (configs_list = (eglconfig *) 0)
Return false;
// Get configurations
If (eglgetconfigs (m_egldisplay, configs_list, num_configs, & num_configs)
= Egl_false | eglgeterror ()! = Egl_success)
Return false;
Due to the restrictions of the current platform, few configurations are usually available. The configuration supported by the system is usually to use the system hardware to provide the best performance. When you port a game to multiple platforms, their EGL configurations may be slightly different. We hope to solve these problems directly as a general porting problem.
Select an EGL Configuration
Based on the EGL attribute, you can define a configuration that you want to obtain from the system. It will return a configuration that is closest to your needs. Selecting a specific configuration is a bit inappropriate, because it is only valid on your platform. The eglchooseconfig () function will adapt to an expected configuration and be as close as possible to an effective system configuration.
The following shows a function prototype for EGL Configuration:
Eglboolean eglchooseconfig (egldisplay dpy, const eglint * attrib_list,
Eglconfig * configs, eglint config_size, eglint * num_config );
The attrib_list parameter specifies the attributes to be referenced during configuration selection. The configs parameter returns a list Of all EGL framebuffer configurations that are effective on the attrib_list platform. The config_size parameter specifies the total number of configurations that can be returned to configs. The num_config parameter returns the total number of actually matched configurations.
The following example shows how to use the eglchoosetconfig () function:
Eglint attrs [3] = {egl_depth_size, 16, egl_none };
Eglint num_configs;
Eglconfigs * configs_list;
// Get the Display Device
If (egldisplay = eglgetdisplay (egl_no_display) = egl_no_display)
{
Return eglgeterror ();
}
// Initialize the display
If (eglinitialize (egldisplay, null, null) = egl_false)
{
Return eglgeterror ();
}
// Obtain the total number of matches that match
If (eglchooseconfig (egldisplay, attrs, null, 0, & num_configs) = egl_false)
{
Return eglgeterror ();
}
Configs_list = malloc (num_configs * sizeof (eglconfig ));
If (configs_list = (eglconfig *) 0)
Return eglgeterror ();
// Obtain the first configuration with a depth buffer of 16 bits
If (! Eglchooseconfig (egldisplay, attrs, & configs_list, num_configs, & num_configs ))
{
Return eglgeterror ();
}
If you find multiple suitable configurations, there is a simple Sorting Algorithm to match the configuration closest to your query. Table 2-2 shows the order in which attribute values are used for selection and sorting. It also includes all EGL configuration attributes and Their default values in The egl specification.
Table 2.1 default values and matching rules of EGL configuration Properties
Attribute |
Data Type |
Default Value |
Sorting priority |
Select order |
Egl_buffer_size |
Int |
0 |
3 |
Smaller value |
Egl_red_size |
Int |
0 |
2 |
Larger Value |
Egl_green_size |
Int |
0 |
2 |
Larger Value |
Egl_blue_size |
Int |
0 |
2 |
Larger Value |
Egl_alpha_size |
Int |
0 |
2 |
Larger Value |
Egl_config_cavet |
Enum |
Egl_dont_care |
1 (First) |
Exact Value |
Egl_config_id |
Int |
Egl_dont_care |
9 |
Exact Value |
Egl_depth_size |
Int |
0 |
6 |
Smaller value |
Egl_level |
Int |
0 |
- |
Equal Value |
Egl_native_renderable |
Boolean |
Egl_dont_care |
- |
Exact Value |
Egl_native_visual_type |
Int |
Egl_dont_care |
8 |
Exact Value |
Egl_sample_buffers |
Int |
0 |
4 |
Smaller value |
Egl_samples |
Int |
0 |
5 |
Smaller value |
Egl_stencil_size |
Int |
0 |
7 |
Smaller value |
Egl_surface_type |
Bitmask |
Egl_window_bit |
- |
Mask Value |
Egl_transparent_type |
Enum |
Egl_none |
- |
Exact Value |
Egl_transparent_red_value |
Int |
Egl_dont_care |
- |
Exact Value |
Egl_transparent_green_value |
Int |
Egl_dont_care |
- |
Exact Value |
Egl_transparent_blue_value |
Int |
Egl_dont_care |
- |
Exact Value |
Initialize EGL
OpenGL ES is a platform-neutral graphics library. Before it can work, it needs to be associated with an actual Window System, which is the same as OpenGL. But the difference is that this part of work has standards, and this standard is EGL. In the OpenGL era, there are different mechanisms on different platforms to associate window systems, WGL on Windows, xgl on X-window, And AGL on Apple OS. The working method and some terms of EGL are close to that of xgl.
The initialization process of OpenGL ES is shown as follows:
Display → config → Surface
Bytes
Context
Bytes
Application → OpenGL command
1. Get display.
Display represents a display. In some systems, multiple displays can be displayed. To obtain the display, call eglboolean eglgetdisplay (nativedisplay dpy). The parameter is generally egl_default_display. The actual meaning of this parameter is related to platform implementation. In X-window, it is the xdisplay ID and in MS Windows, it is the window DC.
2. initialize EGL.
Call eglboolean eglinitialize (egldisplay dpy, eglint * Major, eglint * minor). This function performs some internal initialization and returns the EGL version number (Major. Minor ).
3. select Config.
Config actually refers to the framebuffer parameter, which corresponds to pixelformat in MS Windows and visual in X-window. Eglboolean eglchooseconfig (egldisplay dpy, const eglint * attr_list, eglconfig * config, eglint config_size, eglint * num_config) is generally used, where attr_list is an array of parameters ending with egl_none, values are stored in sequence, and the attribute of individual identifiers can only be
ID, no value. Another method is to use eglboolean eglgetconfigs (egldisplay dpy, eglconfig * config, eglint config_size, eglint * num_config) to obtain all the configurations. Both functions return no more than config_size config, and the results are saved in config []. The total number of system config is saved in num_config. You can use the two parameters in eglgetconfig () to query the total number of configs supported by the system.
Config has many attributes. These attributes determine the format and capability of framebuffer. They can be read through eglgetconfigattrib (), but cannot be modified.
4. Construct the surface.
Surface is actually a framebuffer. You can use eglsurface eglcreatewindowsurface (egldisplay dpy, eglconfig confg, nativewindow win, eglint * cfg_attr) to create a actually displayed surface. The system usually supports two kinds of surface: pixmapsurface and pbuffersurface. These two types are not printable surfaces, and pixmapsurface is a bitmap stored in the system memory, pbuffer is the frame stored in the video memory.
Surface also has some attributes, which can be considered by name. egl_height egl_width implements egl_texture_format egl_texture_target egl_mipmap_texture egl_mipmap_level can be read through eglsurfaceattrib () settings and eglquerysurface.
5. Create context.
From the perspective of the program, OpenGL pipeline is a state machine with a large number of States such as the current color, texture coordinates, transformation matrix, and dirty dyeing mode, these statuses act on elements such as vertex coordinates submitted by the program to form pixels in the frame buffer. In the OpenGL programming interface, context represents this state machine. The main task of a program is to provide elements and set state to context, and occasionally obtain some information from context.
Use eglcontext eglcreatecontext (egldisplay dpy, eglsurface write, eglsurface read, eglcontext * cmd_list) to create a context.
6. Draw.
The application draws through OpenGL API. After a frame is completed, it calls eglswapbuffers (egldisplay dpy, eglcontext CTX) for display.