注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Crayon

只想做自己

 
 
 

日志

 
 

OpenGL 4.4 和 Android  

2015-03-12 16:51:37|  分类: 开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

手机硬件的更新是如此迅速以至于我们开始进入一个手机与高端PC功能无异的时代。它们的区别将只是芯片的功耗不同而已。

我不想让自己听起来像是在推广我们自己的芯片,但我相信Tegra K1是未来即将发生的事物的前瞻。不仅仅发生在我们身上,我希望其他行业也能加入进来,从而使开发者可以为从PC到手机安全地假设一个相对统一的功能集。K1只是首个示例,因为它的GPU核心是Kepler 。而且它不是什么营销手段,它实际上是与运转像GTX780这种神奇事物相同的微架构。几年的血汗与泪水使其成为了可能。并且限于尺寸,功率和热限制,它 只有192个核心(而不是2304个),但它仍具有较强的性能竞争力。更重要的是在功能上它处于一个完全不同的阵营中,因为它支持完整的桌面级 OpenGL4.4,包括几何着色器,镶嵌,计算等,还有像bindless这样的支持其他事物的扩展。

但是Android只支持OpenGL ES,对吗?实际上不是这样的。虽然现在在Android平台上,首选的官方支持的图形API是OpenGL ES,你仍然可以使用EGL在平台上创建一个"大"OpenGL 上下文,前提是你的设备支持它。这使得在不同的操作系统上传输数据很实用,Windows/Linux/Mac/streamOS 都有OpenGL的后台程序,可以快速启动并模拟裁剪平面(clip planes),alpha测试,或者spec中的少数差异。它同样可以作为一个不错的引用渲染后端程序,在ES渲染路径启动和运行之前验证你的端口。

不要担心,你可以在你的app中同时使用GLES和BigGL。实际上,这很简单。最重要的事情在EGL中,它是Android为创建OpenGL上下文而公开的API。Java或C/C++同样可以这样做,但是要注意需要EGL_SPEC.1.4以上版本。

首先,在创建上下文(或者调用任何一个EGL函数)之前,要知道哪个版本的GL最支持当前设备。可以通过简单地调用eglBindAPI(EGL_OPENGL_API)来完成。该API会将EGL切换到桌面OpenGL模式,如果当前设备不支持,则返回EGL_TRUE或者留下未改变的状态并返回EGL_FALSE。鉴于该函数可以切换全局状态,所以最安全的做法是让EGL首先调用它,之后不再调用。

创建完上下文之后,如果eglBindAPI()函数没有切换BigGL模式,你就要和你之前那样创建你的ES上下文。如果切换成功,你可选择性地 创建BigGL上下文。幸运的是,EGL让它简单化。因为我们已经调用了eglBindAPI(EGL_OPENGL_API),EGL已经设置为 BigGL模式,所以我们只需要在配置文件和上下文中调整一些属性即可。

首先,在传递给eglChooseConfig()的配置属性中,我们需要确保 EGL_RENDERABLE_TYPE 设置为 EGL_OPENGL_BIT ,而不是EGL_OPENGL_ES2_BIT.

其次, 传递给函数  eglCreateContext() 的属性也需要稍微调整。对于 ES上下文,通常把 EGL_CONTEXT_CLIENT_VERSION 设为 1, 2 或3, 这取决于你想搭建哪个版本的OpenGL ES.对于BigGL上下文,我们不使用这个属性,所以不要设置。事实上,你可以直接把BigGL的属性列表置空。

粗略地讲,这比较像下面的样本 (为简洁起见,忽视错误检查):

  1. if(eglBindAPI(EGL_OPENGL_API)) 
  2.   // Create a BigGL context... 
  3.   EGLDisplay display = eglGetDisplay(...); 
  4.   eglInitialize(display, ...); 
  5.   const EGLint configAttrs[] = 
  6.   { 
  7.     EGL_SURFACE_TYPE,    EGL_WINDOW_BIT, 
  8.     EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, 
  9.     // backbuffer attributes here... 
  10.     EGL_NONE 
  11.   }; 
  12.   EGLConfig config; 
  13.   EGLint    numConfigs = 0
  14.   eglChooseConfig(display, configAttrs, &config, 1, &numConfigs); 
  15.   EGLint ctxAttrs[] = 
  16.   { 
  17.     EGL_NONE 
  18.   }; 
  19.   eglCreateContext(display, config, EGL_NO_CONTEXT, ctxAttrs); 
  20. else 
  21.   // TODO: Fallback to old ES context creation... 

最后一点问题,也是我对于使用OpenGL或者OpenGL ES的开发人员的一些建议,不论他们基于怎样的平台进行开发。尤其重要的一点是像上面提到的那样在API之间进行切换。并且,不要隐式地链接到GL符号!就算是再多的功能,你都应当使用eglGetProcAddress(), 并且当心不要在上下文中共享函数指针。如果你做了一下比较疯狂的事情,比如在同一个应用中创建了一个BigGL上下文和一个ES上下文,或者创建了像 glDrawElement()这样的函数,在两者的API中都存在,但是可能指向了完全不同的实现方法。这就意味着你应当仅链接到libEGL,所以需 要通过qglGetProcAddress()函数查询所有的符号。

编辑:应当指出的是,从技术的角度讲,通过eglGetProcAddress()可获得的“EGL_KHR_get_all_proc_addresses”应当是目前的核心功能,但是我坚信,既然目前它在Android通用EGL接口上进行了实现,也就意味着它可以单独驱动,这可能在旧版本的Android上无法正常工作。但是如果你正在考虑支持BigGL,你可能不希望旧设备成为你道路上的绊脚石。

特别强调:我强烈建议如果可能的话,任何正在开发的应用程序应该也有GLES渲染路径。BigGL对于开发是实用的,对于一些边缘特性,甚至会更实用,但是有GLES后端同样会帮助Android避免分段存储,并且帮助你的应用更多的曝光在尽可能多的用户面前。

  评论这张
 
阅读(259)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017