EGL接口简介

由于最近需要在JVM上porting JSR239的接口,于是在网上查找到如下的信息。转载过来,以供学习之用。由于JVM的运行平台是Qualcomm的BrewMP,该文档大部分是针对BrewMP的,所以显得很有用。


原文地址:http://lyodev.appspot.com


EGL接口

EGL是OpenGL ES和底层Native平台视窗系统之间的接口。本章主要讲述OpenGL ES的EGL API,以及如何用它创建Context和绘制Surface等,并对用于OpenGL的其他视窗API做了比较分析,比如WGL和GLX。本章中将涵盖如下几个方面:

l         EGL综述

l         EGL主要构成(Display,Context,Configuration)

l         在Brew和Windows CE上使用EGL

l         EGL和其他OpenGL视窗系统的比较

 

EGL介绍

EGL是为OpenGL ES提供平台独立性而设计。在本章中,你将详细地学习每个EGL API,并了解使用EGL时候需要注意的平台特性和限制。OpenGL ES为附加功能和可能的平台特性开发提供了扩展机制,但仍然需要一个可以让OpenGL ES和本地视窗系统交互且平台无关的层。OpenGL ES本质上是一个图形渲染管线的状态机,而EGL则是用于监控这些状态以及维护Frame buffer和其他渲染Surface的外部层。图2-1是一个典型的EGL系统布局图。




EGL视窗设计是基于人们熟悉的用于Microsoft Windows(WGL)和UNIX(GLX)上的OpenGL的Native接口,与后者比较接近。OpenGL ES图形管线的状态被存储于EGL管理的一个Context中。Frame Buffers和其他绘制Surfaces通过EGL API创建、管理和销毁。EGL同时也控制和提供了对设备显示和可能的设备渲染配置的访问。


EGL 数据类型

EGL包含了自己的一组数据类型,同时也提供了对一组平台相关的本地数据类型的支持。这些Native数据类型定义在EGL系统的头文件中。一旦你了解这些数据类型之间的不同,使用它们将变得很简单。多数情况下,为保证可移植性,开发人员将尽可能使用抽象数据类型而避免直接使用系统数据类型。通过使用定义在EGL中Native类型,可以让你写的EGL代码运行在任意的EGL的实现上。Native EGL类型说明如下:

l         NativeDisplayType 平台显示数据类型,标识你所开发设备的物理屏幕

l         NativeWindowType 平台窗口数据类型,标识系统窗口

l         NativePixmapType 可以作为Framebuffer的系统图像(内存)数据类型,该类型只用于离屏渲染

下面的代码是一个NativeWindowType定义的例子。这只是一个例子,不同平台之间的实现千差万别。使用native类型的关键作用在于为开发者抽象化这些细节。QUALCOMM使用IDIB结构定义native类型,如下:

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];

};

接下来的小节中,我们将深入更多EGL数据类型细节。标准EGL数据类型如表2.1所示。

表2.1 EGL 数据类型


数据类型

EGLBoolean

EGL_TRUE =1, EGL_FALSE=0

EGLint

int数据类型

EGLDisplay

系统显示ID或句柄

EGLConfig

Surface的EGL配置

EGLSurface

系统窗口或frame buffer句柄

EGLContext

OpenGL ES图形上下文

NativeDisplayType

Native系统显示类型

NativeWindowType

Native系统窗口缓存类型

NativePixmapType

Native系统frame buffer


EGL Displays


EGLDisplay是一个关联系统物理屏幕的通用数据类型。对于PC来说,Display就是显示器的句柄。不管是嵌入式系统或PC,都可能有多个物理显示设备。为了使用系统的显示设备,EGL提供了EGLDisplay数据类型,以及一组操作设备显示的API。

       下面的函数原型用于获取Native Display:

EGLDisplay eglGetDisplay (NativeDisplayType display);

其中display参数是native系统的窗口显示ID值。如果你只是想得到一个系统默认的Display,你可以使用EGL_DEFAULT_DISPLAY参数。如果系统中没有一个可用的native display ID与给定的display参数匹配,函数将返回EGL_NO_DISPLAY,而没有任何Error状态被设置。

由于设置无效的display值不会有任何错误状态,在你继续操作前请检测返回值。

下面是一个使用EGL API获取系统Display的例子:

m_eglDisplay = eglGetDisplay( system.display);

if (m_eglDisplay == EGL_NO_DISPLAY || eglGetError() != EGL_SUCCESS))

throw error_egl_display;

 

Initialization初始化


    和很多视窗API类似,EGL在使用前需要初始化,因此每个EGLDisplay在使用前都需要初始化。初始化EGLDisplay的同时,你可以得到系统中EGL的实现版本号。了解当前的版本号在向后兼容性方面是非常有价值的。嵌入式和移动设备通常是持续的投放到市场上,所以你需要考虑到你的代码将被运行在形形色色的实现上。通过动态查询EGL版本号,你可以为新旧版本的EGL附加额外的特性或运行环境。基于平台配置,软件开发可用清楚知道哪些API可用访问,这将会为你的代码提供最大限度的可移植性。

       下面是初始化EGL的函数原型:

              EGLBoolean eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);

其中dpy应该是一个有效的EGLDisplay。函数返回时,major和minor将被赋予当前EGL版本号。比如EGL1.0,major返回1,minor则返回0。给major和minor传NULL是有效的,如果你不关心版本号。

       eglQueryString()函数是另外一个获取版本信息和其他信息的途径。通过eglQueryString()获取版本信息需要解析版本字符串,所以通过传递一个指针给eglInitializ()函数比较容易获得这个信息。注意在调用eglQueryString()必须先使用eglInitialize()初始化EGLDisplay,否则将得到EGL_NOT_INITIALIZED错误信息。

       下面是获取EGL版本字符串信息的函数原型:

const char * eglQueryString (EGLDisplay dpy, EGLint name);

参数name可以是EGL_VENDOR, EGL_VERSION, 或者 EGL_EXTENSIONS。这个函数最常用来查询有哪些EGL扩展被实现。所有EGL扩展都是可选的,如果你想使用某个扩展特性,请检查该扩展是否被实现了,而不要想当然假定已经实现了。如果没有扩展被实现,将返回一个Null字符串,如果给定的name参数无效,则会得到EGL_BAD_PARAMETER.错误信息。

EGL Configurations

EGLConfigs是一个用来描述EGL surface配置信息的数据类型。要获取正确的渲染结果,Surface的格式是非常重要的。根据平台的不同,surface配置可能会有限制,比如某个设备只支持16位色深显示,或是不支持stencil buffer,还有其他的功能限制或精度的差异。

       下面是获取系统可用的EGL配置信息的函数原型:

EGLBoolean eglGetConfigs (EGLDisplay dpy, EGLConfig *configs,EGLint config_size, EGLint *num_config);

参数configs将包含在你的平台上有效的所有EGL framebuffer配置列表。支持的配置总数将通过num_config返回。实际返回的configs的配置个数依赖于程序传入的config_size。如果config_size < num_config,则不是所有的配置信息都将被返回。如果想获取系统支持的所有配置信息,最好的办法就是先给eglGetConfig传一个NULL的configs参数,num_config将得到系统所支持的配置总数,然后用它来给configs分配合适的内存大小,再用得到的configs来调用eglGetConfig。

       下面是如果使用eglGetConfig()函数的例子:

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 configurations 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;

由于当前平台的限制,通常只有很少的配置可用。系统支持的配置通常是利用系统硬件提供最好的性能。当你移植游戏到多个平台,它们的EGL配置可能会有细微的差别,我们希望作为通用的移植问题来直接处理这些问题。

 

选择一个EGL Configuration

基于EGL的属性,你可以定义一个希望从系统获得的配置,它将返回一个最接近你的需求的配置。选择一个你特有的配置是有点不合适的,因为只是在你的平台上使用有效。eglChooseConfig()函数将适配一个你所期望的配置,并且尽可能接近一个有效的系统配置。

       下面是选择一个EGL配置的函数原型:

EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,

EGLConfig *configs, EGLint config_size, EGLint * num_config);

参数attrib_list指定了选择配置时需要参照的属性。参数configs将返回一个按照attrib_list排序的平台有效的所有EGL framebuffer配置列表。参数config_size指定了可以返回到configs的总配置个数。参数num_config返回了实际匹配的配置总数。

       下面是如果使用eglChoosetConfig()函数的例子:

       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 configurations 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();

}

如果找到多个合适的配置,有一个简单的排序算法用来匹配最接近你所查询的配置。表2-2显示了基于属性值的用来选择和排序的顺序,也包括了EGL规范中所有EGL配置属性及其默认值。

表2.1 EGL 配置属性默认值和匹配法则

属性

数据类型

默认值

排序优先级

选择顺序

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值