Faster Alternatives to glReadPixels and glTexImage2D in OpenGL ES
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
- GL_PIXEL_PACK_BUFFERhttp://www.khronos.org/opengles/sdk/docs/man3/xhtml/glMapBufferRange.xml
- EGL_KHR_image_basehttp://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
- GL_OES_EGL_imagehttp://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image.txt
- Using direct textures on Android http://snorp.net/2011/12/16/android-direct-texture.html
- 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
- 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的更多相关文章
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
- OpenGL ES无法获取贴图数据原因
最近在做一个项目,要从贴图中获取图像数据,查了很多资料,也琢磨很久,获取到的数据都是0.终于在一次偶然的机会,发现了端倪,成功了. 不得不说这"一分灵感"真的很重要 以下是在获取贴 ...
- 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, ...
- OpenGL ES一些函数详解(一)
glLoadIdentity和glMultMatrix glLoadIdentity的作用是将当前模型视图矩阵转换为单位矩阵(行数和列数相同的矩阵,并且矩阵的左上角至右下角的连线上的元素都为1,其 ...
- 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 这 ...
- OpenGL ES中MRT应用
Demo涵盖了OpenGL ES 3.0 的一系列新特性: 1.VAO和VBO 2.帧缓冲对象 3.MRT 效果: 代码: //yf's version #define STB_IMAGE_IMPLE ...
- Android OpenGL ES 开发(N): OpenGL ES 2.0 机型兼容问题整理
在使用OpenGL ES做开发的时候,发现不是所有机型对OpenGL的代码都兼容的那么好,同样的代码在某些机型上总是会出现问题,但是在其他手机上就是好的.下面是本人总结的OpengGL 兼容问题: 一 ...
- 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
片段操作图 这篇文章将介绍从写入帧缓冲和读取帧缓冲的方式. Buffers(缓冲) OpenGL ES支持三种缓冲: OpenGL ES •• Color buffer颜色缓冲 •• Depth bu ...
随机推荐
- [错误记录_C] 还未给指针变量正确赋值的情况下,就使用它的值
错误的代码: 错误的结果: 错误原因分析: 在使用(1) 将pB,pC的值赋给pA的lchild和rchild时: 还未给指针变量pB和pC赋值,现在pB和pC中存的是个垃圾值 Note: (2)- ...
- PHP DES解密 对应Java SHA1PRNG方式加密
背景及问题 背景:在和外部系统通过HTTP方式跳转时, 为保障传输参数安全性, 采用AES 加密参数. 关于对称加密中 AES, DES, CBC, ECB, PKCS5Padding 概念可参考ht ...
- 介绍一款小众的IDE
作为前端工程师的你们平时主要使用什么IDE,atom.webstorm.sublime还是vscode? 今天介绍一款比较小众的IDE,Adobe的开源项目Brackets,提供Windows和OS ...
- Echarts按需引入后没有显示图例问题
因为Echarts官网的例子都是引入整个Echarts.js.如果使用按需引入对应模块就要记得引入legend模块,才能显示出图例. 例如这样: require("echarts/lib/c ...
- python anaconda 安装 环境变量 升级 以及特殊库安装
Anaconda 是一个旗舰版的python安装包, 因为普通的python没有库, 如果需要安装一些重要的库, 要经常一个一个下载,会非常麻烦. 所以这个一个集成的, 可以手动批量升级的软件. 而且 ...
- Infor SyteLine如何快速锁定用户
使用Infor Syteline ERP系统,当需要做系统维护时,我们需要通知所有用户退出系统,在维护期间,严禁用户登录,这样的话,我们需要锁定用户.对于这个问题,很多管理员会打开SL的Users窗口 ...
- RxJava 中的map与flatMap
1.map和flatMap都是接受一个函数作为参数(Func1) 2.map函数只有一个参数,参数一般是Func1,Func1的<I,O>I,O模版分别为输入和输出值的类型,实现Func1 ...
- arm汇编学习(四)
一.android jni实现1.静态实现jni:先由Java得到本地方法的声明,然后再通过JNI实现该声明方法.2.动态实现jni:先通过JNI重载JNI_OnLoad()实现本地方法,然后直接在J ...
- linux常用命令(50个)
1. find 基本语法参数如下: find [PATH] [option] [action] # 与时间有关的参数: -mtime n : n为数字,意思为在n天之前的“一天内”被更改过的文件: - ...
- Oracle IMPDP导入数据案例之注意事项(undo/temp)
针对Oracle数据迁移,我们可能会用到expdp/impdp的方式,有时候需要大表.lob字段等可能会消耗过大的临时表空间和undo表空间,所以一般我们根据导出日志,在导入前适当调整表空间大小.否则 ...