Quantcast
Channel: Mali Developer Center
Viewing all articles
Browse latest Browse all 125

选择正确的 EGLConfig

$
0
0

 

简介

每一硬件平台都有其独特的显示配置,具体取决于 LCD 面板(或 HDMI 等外部视频输出)属性、LCD 控制器、GPU,以及可用的内存和带宽。 EGL 使用 EGLConfig 抽象来实现跨平台移植。 对于每一个给定的硬件平台,每个 EGLConfig 与可能的显示配置对应。

为了创建“表面”(用于渲染输出的目标缓存的 EGL 术语),有必要提供 EGLConfig。 此 EGLConfig 必须从所有可用范围中选定,具体通过发出详细说明您所需要的特性(指代为属性)的请求来进行。

这一示例演示如何在创建表面时从可用范围中选择正确的 EGLConfig。

/* Get a display handle and initalize EGL */
EGLint major, minor;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, &major, &minor);

/* Request an RGB565 config. with 4x anti-aliasing
* (4x is 'free' on Mali :-) 
*/
EGLint attributes = { EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_SAMPLES, 4,
EGL_NONE }
EGLint numberConfigs;
EGLConfig* matchingConfigs;
/* Number of matching EGLConfig's returned in numberConfigs, but because
* the 3rd argument is NULL no configs will actually be returned
*/
if (EGL_FALSE == eglChooseConfig(display, attributes, NULL,0, &numberConfigs)) 
{
/* An error */
}
if (numberConfigs == 0) {
/* An error */
}

/* Allocate some space to store list of matching configs... */
matchingConfigs = (EGLConfig*)malloc( numberConfigs * sizeof(EGLConfig));
/* ...and this time actually get the list (notice the 3rd argument is
* now the buffer to write matching EGLConfig's to)
*/
if (EGL_FALSE == eglChooseConfig(display, attributes, matchingConfigs, numberConfigs, &numberConfigs)) 
{
/* An error */
}

 

潜在问题
EGL 并不等同对待所有属性,并且在一些情形中,EGL 不会查找完全匹配项。例如,如果请求在 Z 缓存 (EGL_DEPTH_SIZE) 中具有一定数量的位的 EGLConfig,它会被视为最小值。 位数较高的 EGLConfig 依然会被考虑。 如果有多个匹配的 EGLConfig,则它们都会被返回。

另外,EGL 将兼容的 EGLConfig 按照 EGL 规格中定义的特定顺序进行排序。 此顺序并非始终都明了。

为了说明这两项原则,请以某一需要 16 位色的应用程序为例。 为了这一目的,它可能会请求一个值为 5 的 EGL_RED_SIZE、一个值为 6 的 EGL_GREEN_SIZE,以及一个值为 5 的 EGL_BLUE_SIZE 。颜色通道深度是视为最小值的属性,因此兼容 EGLConfig 的列表将包含所有 16 位颜色深度,以及更多颜色的深度,如 EGL_RED_SIZE 等于 8、 EGL_GREEN_SIZE 等于 8,以及 EGL_BLUE_SIZE 等于 8。由于找到了多个匹配的 EGLConfig,驱动程序将对它们进行排序。 颜色通道深度属性的排序行为意味着颜色数较高的 EGLConfig 将排在前列。 因此,尽管请求了 16 位显示,列表中的第一个 EGLConfig 实际上是 24/32 位显示。

此外,还有一个优先级的概念用来确定用于对匹配的 EGLConfig 进行排序的顺序属性。为了进行说明,我们假设将值为 16 的 EGL_BUFFER_SIZE 添加到请求中的属性列表中。 EGL_BUFFER_SIZE 是总的颜色缓存深度。EGL_BUFFER_SIZE 的排序顺序是从最小到最大,因此似乎能够解决上述的问题,因为第一个 EGLConfig 将是 16 位显示。 遗憾的是,这依然不行。因为 EGL_BUFFER_SIZE 属性的优先级低于EGL_[RED|GREEN|BLUE]_SIZE。 这表示驱动程序依然会根据各个颜色通道的最大值来排序。 为了获得 16 位颜色缓存,必须从请求中删除较高优先级的个别颜色通道属性。

最后,还得考虑请求中的属性是否足够精确。 如果请求中仅包含值为 16 的 EGL_BUFFER_SIZE 的属性,它会选择颜色缓存总深度为16 位的EGLConfig,但这可以是 RGB565、RGBA5551 或 RGBA4444。 如果 EGLConfig 的目的是为了绘制OS 位图 [1],则务必要精确匹配格式 [2]。

后果
根据平台的不同,尤其是在颜色深度的情形中,EGLConfig 选择不当可能会降低性能或导致运行时错误。 例如,在颜色深度/格式不匹配时,GPU 可能必须要渲染至离屏临时缓冲区(需要额外内存),接着 CPU 必须将各个像素从选定的格式转换为实际需要的格式,并且最终拷贝至实际目的地(过程中消耗许多 CPU 周期)。

/* The EGLConfig we will eventually use.
* Set to NULL to detect the case where no suitable config. Is found
*/
EGLConfig chosenConfig = NULL;

/* Look at each EGLConfig */
for (int ii=0; ii<numberConfigs; ii++) 
{
	EGLBoolean success;
	EGLint red, green, blue;
	/* Read the relevent attributes of the EGLConfig */
	success = eglGetConfigAttrib(display, matchingConfigs[ii],
	EGL_RED_SIZE, &red);
	success &= eglGetConfigAttrib(display, matchingConfigs[ii],
	EGL_BLUE_SIZE, &blue);
	success &= eglGetConfigAttrib(display, matchingConfigs[ii],
	EGL_GREEN_SIZE, &green);

	/* Check that no error occurred and the attributes match */
	if ( success == EGL_TRUE) && (red==5) && (green==6) && (blue==5) ) 
	{
		chosenConfig=match[ii];
		break;
	}
}

if (chosenConfig == NULL) 
{
	/* An error */
}

free(matchingConfigs);

 

结论
我们可以从上述注释中清楚地认识到,如果应用程序或平台对 EGLConfig 有具体的要求,则必须要小心操作以便在请求中使用正确的属性;而且,如果有可能返回任何不适当的 EGLConfig,则应检查各个 EGLConfig 的相关属性。

这是该主题的简单介绍;EGL 规格中详述了精确选择、排序和优先级行为,您可从 http://www.khronos.org/registry/egl/ 获取该规格。

建议您阅读(至少)第 3.4 节“配置管理”。

额外信息
本示例的完整源代码列表在 OpenGL ES SDK for Linux on ARM 和 OpenGL ES 2.0 SDK for Android 中提供,其中还提供了演示其用法的许多其他示例。

OpenGL ES SDK

 


Viewing all articles
Browse latest Browse all 125

Trending Articles