解决android opengl glReadPixels 慢的问题一
16lz
2021-01-26
解决android opengl glReadPixels 慢的问题
由于android的gpu跟cpu内存是分离的,导致数据拷贝的过程中会非常慢,网上资料相对较少,下面是我解决这个问题的一点心的,使用PBO代码如下
1. 初始化纹理方法
public static int loadTexture(final Bitmap img, final int usedTexId, int i) {if(img == null)return NO_TEXTURE;//ByteBuffer img_buffer = ByteBuffer.allocate(img.getByteCount());//img.copyPixelsToBuffer(img_buffer);ByteBuffer pbo_point = null; int textures[] = new int[1]; if (usedTexId == NO_TEXTURE) { GLES30.glGenTextures(1, textures, 0); GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]); GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR); GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR); GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE); GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE); GLES30.glGenBuffers(1, pbo); GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, pbo.get(0)); GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER,width*height*4, null, GLES30.GL_DYNAMIC_READ); GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0); GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, img, 0); } else { GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, usedTexId);// GLUtils.texSubImage2D(GLES30.GL_TEXTURE_2D, 0, 0, 0, img); textures[0] = usedTexId; } return textures[0]; }
2. 初始化PBO
public static int loadFramebuffer(int texture, int width,int height){IntBuffer framebuffer = IntBuffer.allocate(1);IntBuffer depthRenderbuffer = IntBuffer.allocate(1);IntBuffer max = IntBuffer.allocate(10);int temp = 0;GLES30.glGetIntegerv(GLES30.GL_MAX_RENDERBUFFER_SIZE, max);temp = max.get(0);if (temp <= width && temp <= height){return -1;}GLES30.glGenFramebuffers(1, framebuffer);GLES30.glGenRenderbuffers(1, depthRenderbuffer);GLES30.glBindRenderbuffer(GLES30.GL_RENDERBUFFER, depthRenderbuffer.get(0));GLES30.glRenderbufferStorage(GLES30.GL_RENDERBUFFER, GLES30.GL_RGBA, width, height);GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer.get(0));GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, texture, 0);GLES30.glFramebufferRenderbuffer(GLES30.GL_FRAMEBUFFER,GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_RENDERBUFFER, depthRenderbuffer.get(0));int status = 0;status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);if (status == GLES30.GL_FRAMEBUFFER_COMPLETE){Log.d(TAG,"frame buffer init ok!!!!!!!");GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);GLES30.glDeleteRenderbuffers(1, depthRenderbuffer);GLES30.glDeleteFramebuffers(1, framebuffer);return framebuffer.get();}Log.d(TAG,"frame buffer init file!!!!!!!");return -1;}
3. surface creat 初始化
public void onSurfaceCreated ( GL10 glUnused, EGLConfig config ) { String vShaderStr = "attribute vec4 position;\n" + "attribute vec4 inputTextureCoordinate;\n" + " \n" + "varying vec2 textureCoordinate;\n" + " \n" + "void main()\n" + "{\n" + " gl_Position = position;\n" + " textureCoordinate = inputTextureCoordinate.xy;\n" + "}"; String fShaderStr = "precision highp float; \n" + "varying highp vec2 textureCoordinate;\n" + "uniform sampler2D inputImageTexture;\n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" + "} \n"; int vertexShader; int fragmentShader; int programObject; int[] linked = new int[1]; // Load the vertex/fragment shaders vertexShader = LoadShader ( GLES30.GL_VERTEX_SHADER, vShaderStr ); fragmentShader = LoadShader ( GLES30.GL_FRAGMENT_SHADER, fShaderStr ); // Create the program object programObject = GLES30.glCreateProgram(); if ( programObject == 0 ) { return; } GLES30.glAttachShader ( programObject, vertexShader ); GLES30.glAttachShader ( programObject, fragmentShader ); // Bind vPosition to attribute 0 GLES30.glBindAttribLocation ( programObject, 0, "vPosition" ); // Link the program GLES30.glLinkProgram ( programObject ); // Check the link status GLES30.glGetProgramiv ( programObject, GLES30.GL_LINK_STATUS, linked, 0 ); if ( linked[0] == 0 ) { Log.e ( TAG, vShaderStr ); Log.e ( TAG, fShaderStr ); Log.e ( TAG, "Error linking program:" ); Log.e ( TAG, GLES30.glGetProgramInfoLog ( programObject ) ); GLES30.glDeleteProgram ( programObject ); return; } // Store the program object mProgramObject = programObject; mGLAttribPosition = GLES30.glGetAttribLocation(programObject, "position"); mGLUniformTexture = GLES30.glGetUniformLocation(programObject, "inputImageTexture"); mGLAttribTextureCoordinate = GLES30.glGetAttribLocation(programObject, "inputTextureCoordinate"); Log.d(TAG,"id = " + color_id + "mGLUniformTexture= " + mGLUniformTexture); // GLES30.glClearColor ( 1.0f, 1.0f, 1.0f, 0.0f ); }
4. 最后使用pbo 画出来
public void onDrawFrame ( GL10 glUnused ) { index++; mTextureId = loadTexture(bitmap,mTextureId,0); // Set the viewport GLES30.glViewport ( 0, 0, width ,height); // Clear the color buffer GLES30.glClearColor(0.0f,0.0f,0.0f,0.0f); GLES30.glClear ( GLES30.GL_COLOR_BUFFER_BIT ); // Use the program object GLES30.glUseProgram ( mProgramObject ); mVertices.position(0); GLES30.glVertexAttribPointer ( mGLAttribPosition, 3, GLES30.GL_FLOAT, false, 0, mVertices ); GLES30.glEnableVertexAttribArray ( mGLAttribPosition ); mGLTextureBuffer.position(0); GLES30.glVertexAttribPointer ( mGLAttribTextureCoordinate, 2, GLES30.GL_FLOAT, false, 0, mGLTextureBuffer ); GLES30.glEnableVertexAttribArray ( mGLAttribTextureCoordinate ); // if (mTextureId >= 0) { //loadFramebuffer(mTextureId,width,height); GLES30.glActiveTexture(GLES30.GL_TEXTURE0); GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId); GLES30.glUniform1i(mGLUniformTexture, 0); } GLES30.glDrawArrays ( GLES30.GL_TRIANGLE_STRIP, 0, 4 ); Log.d("jni", "刷新时间"); return; }
总结:虽然使用一个PBO但是效果改变不是很明显,因为单个PBO传输还是需要等待的,假如使用2个pbo,这样错开接收就会使效率大大提高,请看下篇使用2个PBO速度慢的问题。
更多相关文章
- 【实践驱动开发3-004】TI WL1835MODCOM8 在android的移植 - 系统
- android复杂首页布局
- android asmack调用MultiUserChat.getHostedRooms方法出现空指针
- Android(安卓)系统的Zygote初始化过程
- Android(安卓)SoundPool sample 1 not ready错误解决方法
- android loading界面 及 处理
- android 【点击输入框调出输入法前的】输入框获取焦点和输入法的
- android轻量级数据存储框架Hawk
- Android中RadioGroup的初始化和简单的使用