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 ...
随机推荐
- 互联网轻量级框架SSM-查缺补漏第二天
简言:第一天没咋看,因为看的时候已经是下午了.今天上午也因为工作上的事没咋看,本来想按照天去写的,但是内容会太散吧.我决定把整块的内容放在一起写了.天数啥的,就那样把. 还有,我只是言简意赅的去总结一 ...
- cygwin 的安装和配置
Cygwin是一个在windows平台上运行的类UNIX模拟环境,是cygnus solutions公司开发的自由软件(该公司开发的著名工具还有eCos,不过现已被Redhat收购).它对于 ...
- POJ 2955 Brackets 区间DP 最大括号匹配
http://blog.csdn.net/libin56842/article/details/9673239 http://www.cnblogs.com/ACMan/archive/2012/08 ...
- Oracle自定义函数&加密
在sql中频繁使用的功能(逻辑.加密等)可以写成自定义函数进行封装,之后再调用即可. CREATE OR REPLACE FUNCTION "函数名" (参数名 参数类型 参数数据 ...
- Docker问题集合
1. 安装后启动出现 解决办法: 删除以下文件夹重新启动docker服务即可: 可能原因:(1) 之前docker进程出现错误并保存在keys.json文件中 (2) 删除之前配置了阿里云镜像,生成了 ...
- 重构指南 - 分解复杂判断(Remove Arrowhead Antipattern)
当代码中有多层嵌套时,会降低代码的可读性,对于以后的修改也增加难度,所以我们需要分解复杂的判断并尽快返回. 重构前代码 public class Security { public ISecurity ...
- php编程--二叉树遍历算法实现
今天使用php来实现二叉树的遍历 创建的二叉树如下图所示 php代码如下所示: <?php class Node { public $value; public $child_l ...
- MySQL创建子视图并查看的时候,字符集报错问题
进入命令行模式, 如果MySQL数据库已经安装好,可以使用下列SQL命令查看MySQL当前的字符集设置: mysql> show variables like 'character_set_%' ...
- CentOS 7运维管理笔记(6)----Apache 基于 IP 的虚拟主机配置
Apache 配置虚拟主机支持3种方式:基于IP的虚拟主机配置,基于端口的虚拟主机配置,基于域名的虚拟主机配置.本篇随笔记录自己基于IP的虚拟主机配置. 如果同一台服务器有多个IP,可以使用基于IP的 ...
- UMTSkeeper: keep your UMTS/GPRS/GSM connection alive automatically
UMTSkeeper: keep your UMTS/GPRS/GSM connection alive automatically by Elias from Mintaka This page i ...