In the development of Shou, I’ve been using GLSL with NEON to manipulate image rotation, scaling and color conversion, before send them to video encoder.

So I need a very efficient way to transfer pixels between OpenGL and memory space. TheglTexImage2D and glReadPixels performance are very unacceptable, especially for some specific vendors, e.g. Samsung Galaxy devices with Exynos chip.

Compared to glTex(Sub)Image2D, the glReadPixels is the real bottleneck, which blocks all OpenGL pipeline and results in about 100ms delay for a standard 720P frame read back.

Here I will share two standard OpenGL approaches to achieve really faster pixels pack, which should be available on all OpenGL implementations. Only glReadPixels will be discussed, as the glTexImage2D should have the same usage.

Pixel Buffer Object

PBO is not introduced until OpenGL ES 3.0, which is available since Android 4.3. The pixels pack operation will be reduced to about 5ms using PBO.

PBO is created just like any other buffer objects:

glGenBuffers(, &pbo_id); glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id); glBufferData(GL_PIXEL_PACK_BUFFER, pbo_size, , GL_DYNAMIC_READ); glBindBuffer(GL_PIXEL_PACK_BUFFER, );

According to the reference of glReadPixels:

If a non-zero named buffer object is bound to the GL_PIXEL_PACK_BUFFER target (see glBindBuffer) while a block of pixels is requested, data is treated as a byte offset into the buffer object’s data store rather than a pointer to client memory.

When we need to read pixels from an FBO:

glReadBuffer(GL_COLOR_ATTACHMENT0); glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id); glReadPixels(, , width, height, GL_RGBA, GL_UNSIGNED_BYTE, ); GLubyte *ptr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, , pbo_size, GL_MAP_READ_BIT); memcpy(pixels, ptr, pbo_size); glUnmapBuffer(GL_PIXEL_PACK_BUFFER); glBindBuffer(GL_PIXEL_PACK_BUFFER, );

In a real project, we may consider using double or triple PBOs to improve the performance.

EGLImage

EGL_KHR_image_base is a completed EGL extension, which achieves the same performance as PBO, but only require OpenGL-ES 1.1 or 2.0.

The function to create an EGLImageKHR is

EGLImageKHR eglCreateImageKHR(EGLDisplay dpy,                               EGLContext ctx,                               EGLenum target,                               EGLClientBuffer buffer,                               const EGLint *attrib_list)

The Android EGL implementation frameworks/native/opengl/libagl/egl.cpp implies that theEGLDisplay should be a valid display, the EGLClientBuffer type should be ANativeWindowBuffer, the EGLContext can only be EGL_NO_CONTEXT, and the target can only beEGL_NATIVE_BUFFER_ANDROID.

All the other parameters are obvious, except for the ANativeWindowBuffer, which is defined insystem/core/include/system/window.h.

To allocate an ANativeWindowBuffer, Android has a simple wrapper called GraphicBuffer, defined in frameworks/native/include/ui/GraphicBuffer.h.

GraphicBuffer *window = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE);  struct ANativeWindowBuffer *buffer = window->getNativeBuffer(); EGLImageKHR *image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, *attribs);

Then anytime we want to read pixels from an FBO, we should use one of the two methods below:

void EGLImageTargetTexture2DOES(enum target, eglImageOES image)  void EGLImageTargetRenderbufferStorageOES(enum target, eglImageOES image)

These two methods will establishes all the properties of the target GL_TEXTURE_2D orGL_RENDERBUFFER.

uint8_t *ptr; glBindTexture(GL_TEXTURE_2D, texture_id); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);  window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &ptr); memcpy(pixels, ptr, width * height * ); window->unlock();

References

  1. GL_PIXEL_PACK_BUFFERhttp://www.khronos.org/opengles/sdk/docs/man3/xhtml/glMapBufferRange.xml
  2. EGL_KHR_image_basehttp://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
  3. GL_OES_EGL_imagehttp://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image.txt
  4. Using direct textures on Android http://snorp.net/2011/12/16/android-direct-texture.html
  5. Using OpenGL ES to Accelerate Apps with Legacy 2D GUIs http://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis
  6. iOS solution http://stackoverflow.com/questions/9550297/faster-alternative-to-glreadpixels-in-iphone-opengl-es-2-0

Faster Alternatives to glReadPixels and glTexImage2D in OpenGL ES的更多相关文章

  1. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  2. OpenGL ES无法获取贴图数据原因

    最近在做一个项目,要从贴图中获取图像数据,查了很多资料,也琢磨很久,获取到的数据都是0.终于在一次偶然的机会,发现了端倪,成功了. 不得不说这"一分灵感"真的很重要 以下是在获取贴 ...

  3. Beginning OpenGL ES 2.0 with GLKit Part 1

    Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, ...

  4. OpenGL ES一些函数详解(一)

    glLoadIdentity和glMultMatrix   glLoadIdentity的作用是将当前模型视图矩阵转换为单位矩阵(行数和列数相同的矩阵,并且矩阵的左上角至右下角的连线上的元素都为1,其 ...

  5. Android OpenGL ES(十四)gl10方法解析

    Android 支持 OpenGL 列表 1.GL 2.GL 10 3.GL 10 EXT 4.GL 11 5.GL 11 EXT 6.GL 11 ExtensionPack 我们将使用 GL10 这 ...

  6. OpenGL ES中MRT应用

    Demo涵盖了OpenGL ES 3.0 的一系列新特性: 1.VAO和VBO 2.帧缓冲对象 3.MRT 效果: 代码: //yf's version #define STB_IMAGE_IMPLE ...

  7. Android OpenGL ES 开发(N): OpenGL ES 2.0 机型兼容问题整理

    在使用OpenGL ES做开发的时候,发现不是所有机型对OpenGL的代码都兼容的那么好,同样的代码在某些机型上总是会出现问题,但是在其他手机上就是好的.下面是本人总结的OpengGL 兼容问题: 一 ...

  8. 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  9. OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)

    片段操作图 这篇文章将介绍从写入帧缓冲和读取帧缓冲的方式. Buffers(缓冲) OpenGL ES支持三种缓冲: OpenGL ES •• Color buffer颜色缓冲 •• Depth bu ...

随机推荐

  1. Spring相关概念的理解理解

    spring 框架的优点是一个轻量级比较简单易学的框架,实际使用中的有点优点有哪些呢!1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3 ...

  2. class path resource [logback.xml] cannot be resolved to URL because it does not exist 问题解决

    今天在自己搭建Springboot 框架的时候,在配置 logging.config=classpath:logback.xml 出现找不到这个文件的错误 经发现是maven的一个写法问题,本来我是打 ...

  3. 微信公众号开发《三》微信JS-SDK之地理位置的获取与在线导航,集成百度地图实现在线地图搜索

    本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...

  4. HTML5数据存储方案data与jQuery数据存储方案$.data()的区别

    我们先看下$.fn.data()的使用,这个和$.data()是不一样的,前者是和某个jquery对象相关,后者则是全局方法.主要有data()和removeData()这2个实例方法.通过下面的例子 ...

  5. 第7章 征服CSS3选择器(下)

    :enabled选择器 在Web的表单中,有些表单元素有可用(":enabled")和不可用(":disabled")状态,比如输入框,密码框,复选框等.在默认 ...

  6. JS之原型式的继承

    创建一个Person的构造器 function Person(first, last, age, gender, interests) { this.name = { first, last }; t ...

  7. Jquery trigger 与 triggerHandler

    secying Jquery trigger与triggerHandler trigger: 在每一个匹配的元素上触发某类事件(即触发jQuery对象集合中每一个元素). 这个函数也会导致浏览器同名的 ...

  8. 原生js制作标题与内容保持4行的效果

    在制作网页或移动端有时会用到一个效果,类似文章标题和文章描述的排列总是保持一样的行数,要么标题总是一行,多出的省略,要么标题内容1:3或2:2或3:1这样,今天练习这样的效果. 实现的原理:给标题和内 ...

  9. EMSAscript

    1.javaScript 中const.var.let区别 const 定义的变量不可修改 而且必须初始化 =>解决闭包变量污染问题 var 定义的变量可以修改 如果不初始化则默认值为undef ...

  10. world特殊控制符输入

    特殊符号的输入表示法. 1,“^l”表示软回车(象这种“↓”). 2,“^p”表示硬回车. 3,“^t”表示制表符. 4,“^m”表示手动分页符. 5,“^+”表示长划线(—). 6,“^=”表示短划 ...