解决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速度慢的问题。

更多相关文章

  1. 【实践驱动开发3-004】TI WL1835MODCOM8 在android的移植 - 系统
  2. android复杂首页布局
  3. android asmack调用MultiUserChat.getHostedRooms方法出现空指针
  4. Android(安卓)系统的Zygote初始化过程
  5. Android(安卓)SoundPool sample 1 not ready错误解决方法
  6. android loading界面 及 处理
  7. android 【点击输入框调出输入法前的】输入框获取焦点和输入法的
  8. android轻量级数据存储框架Hawk
  9. Android中RadioGroup的初始化和简单的使用

随机推荐

  1. android饼状图表
  2. Android(安卓)SDK Manager无法更新问题解
  3. Android__TextView跑马灯的实现
  4. Android 如何找到最匹配资源
  5. android Webview支持input type=file
  6. 之View state changes(视图状态改变)
  7. Android Support Library更新到v22.1之Ap
  8. Android 屏幕旋转后防止重新执行onCreate
  9. Activity或者FragmenitActivity锁屏后会
  10. android 中Java和javascript的交互